Summary
A vulnerability in Vaultwarden's SSO login flow allowed an attacker who controlled an IdP identity asserting the victim's email address to bind that identity to the victim's existing Vaultwarden account and authenticate as the victim.
The IdP's email_verified claim was checked in the new-user creation branch but not in the existing-user binding branch of the SSO login handler. Combined with the default SSO_SIGNUPS_MATCH_EMAIL=true, this allowed an email match alone to be treated as sufficient authority for linking a new SSO identity to a pre-existing Vaultwarden account.
Affected versions
All Vaultwarden versions with SSO support up to and including 1.35.8. Versions 1.36.0 and up are fixed.
Root cause
The SSO login handler resolves the incoming IdP identity in three steps:
- Look up an existing
SsoUser by stable identifier (issuer + subject).
- If none, fall back to looking up a local user by the IdP-supplied email.
- If a local user is found, complete the login and persist a new SSO binding.
The email_verified gate was applied only on the new-user branch (step 3 with no local match). On the existing-user branch, the IdP-supplied email was trusted as proof of ownership without consulting the email_verified claim. An IdP identity could therefore claim a victim's email — verified or not — and the resulting login flow would proceed against the victim's account.
Attack chain
- The attacker registers an identity at the configured IdP whose
email claim equals the victim's Vaultwarden email. The IdP may set email_verified to false or omit it.
- The attacker initiates SSO login at Vaultwarden and authenticates at the IdP as the attacker's identity.
sso_login finds no SsoUser by identifier, falls back to lookup by email, and matches the victim's existing local account.
- With no
email_verified check on this branch, the flow proceeds to the 2FA gate. If the victim has no Vaultwarden 2FA configured, a session for the victim's account is issued to the attacker.
- A new SSO binding linking the attacker's IdP subject to the victim's user UUID is persisted, providing repeat access.
Impact
- Account takeover of SSO-eligible victims without Vaultwarden 2FA whose email matches an IdP identity the attacker can obtain.
- Full read of the victim's encrypted vault material (
Key, PrivateKey, ciphers), enabling offline brute-force of the master password.
- Authenticated session actions: device registration, emergency-access grant creation, cipher modification and deletion.
- Potential org-level privilege escalation if the victim holds Owner privileges in any organization.
- Persistent SSO binding remains attached to the victim's account after the session expires.
Preconditions
- SSO is enabled on the Vaultwarden instance.
SSO_SIGNUPS_MATCH_EMAIL=true (default).
- The victim has an existing Vaultwarden account whose email matches an IdP identity the attacker can obtain, and no prior SSO binding exists for that account.
- The victim does not have Vaultwarden 2FA enabled — 2FA blocks the final session issuance but does not prevent the IdP binding from being attempted.
- The configured IdP allows registering an identity with the victim's email. Realistic for self-service, multi-tenant, or weakly governed IdPs; unrealistic for IdPs that strongly enforce domain ownership.
Fix
The patched version applies the email_verified gate to the existing-user binding branch, mirroring the check already enforced on the new-user branch. An IdP that does not assert email_verified=true (or that sets it to false) is now rejected at SSO login regardless of which branch the identity resolution lands on.
Operator guidance
The fix relies on the IdP truthfully reporting email_verified. Operators whose IdP cannot strongly enforce email ownership (self-service registration without verification, multi-tenant deployments without domain controls, or instances with custom claim mappings) should set SSO_SIGNUPS_MATCH_EMAIL=false to require explicit action before binding a new SSO identity to an existing local account.
References
- OIDC Core 1.0 §5.1 —
email_verified claim semantics
- Bitwarden upstream SSO trust model: invite-acceptance flow in
AccountController.cs
Credits
Independently reported by:
Individual roles are listed in the Credits section of this advisory.
Summary
A vulnerability in Vaultwarden's SSO login flow allowed an attacker who controlled an IdP identity asserting the victim's email address to bind that identity to the victim's existing Vaultwarden account and authenticate as the victim.
The IdP's
email_verifiedclaim was checked in the new-user creation branch but not in the existing-user binding branch of the SSO login handler. Combined with the defaultSSO_SIGNUPS_MATCH_EMAIL=true, this allowed an email match alone to be treated as sufficient authority for linking a new SSO identity to a pre-existing Vaultwarden account.Affected versions
All Vaultwarden versions with SSO support up to and including 1.35.8. Versions 1.36.0 and up are fixed.
Root cause
The SSO login handler resolves the incoming IdP identity in three steps:
SsoUserby stable identifier (issuer + subject).The
email_verifiedgate was applied only on the new-user branch (step 3 with no local match). On the existing-user branch, the IdP-supplied email was trusted as proof of ownership without consulting theemail_verifiedclaim. An IdP identity could therefore claim a victim's email — verified or not — and the resulting login flow would proceed against the victim's account.Attack chain
emailclaim equals the victim's Vaultwarden email. The IdP may setemail_verifiedtofalseor omit it.sso_loginfinds noSsoUserby identifier, falls back to lookup by email, and matches the victim's existing local account.email_verifiedcheck on this branch, the flow proceeds to the 2FA gate. If the victim has no Vaultwarden 2FA configured, a session for the victim's account is issued to the attacker.Impact
Key,PrivateKey, ciphers), enabling offline brute-force of the master password.Preconditions
SSO_SIGNUPS_MATCH_EMAIL=true(default).Fix
The patched version applies the
email_verifiedgate to the existing-user binding branch, mirroring the check already enforced on the new-user branch. An IdP that does not assertemail_verified=true(or that sets it tofalse) is now rejected at SSO login regardless of which branch the identity resolution lands on.Operator guidance
The fix relies on the IdP truthfully reporting
email_verified. Operators whose IdP cannot strongly enforce email ownership (self-service registration without verification, multi-tenant deployments without domain controls, or instances with custom claim mappings) should setSSO_SIGNUPS_MATCH_EMAIL=falseto require explicit action before binding a new SSO identity to an existing local account.References
email_verifiedclaim semanticsAccountController.csCredits
Independently reported by:
Individual roles are listed in the Credits section of this advisory.