@better-auth/sso: Personal SSO providers can sign in as another provider's users
What fixes it
- 1.7.3@better-auth/sso, npmGitHub
npm install @better-auth/sso@1.7.3
A fixed version on one release line is not the upgrade target for every line. Check your exact version and any vendor backports.
Description
Am I affected?
You may be affected if you use @better-auth/sso 1.7.0-rc.2 through 1.7.0-rc.6 or 1.7.0 through 1.7.2, and all of these conditions hold:
- An attacker can register a personal SSO provider or use one they registered earlier. Registration is enabled by default for signed-in users, with a limit of 10 providers each.
- Your application has not configured
resolveUser. - A victim's account is linked through another OpenID Connect (OIDC) or SAML provider, and the attacker can reproduce that provider's identity and the victim's account identifier.
Configuring resolveUser requires an exact provider match and blocks this path. Setting providersLimit: 0 only stops new registrations; existing providers remain usable.
Summary
The SSO plugin lets signed-in users register an OIDC or SAML provider. In affected versions, sign-in through a personal provider could match an account linked through a different provider and create a session for that account.
Impact
An attacker with a Better Auth account can register a provider that copies a real provider's identity and reproduces a victim's user identifier. Better Auth then creates a new session for the victim's account without victim interaction.
The attack does not compromise the real identity provider or steal the victim's existing session.
Patches
Upgrade @better-auth/sso to 1.7.3 or later. The fix prevents one provider from matching an account linked through another provider.
Workarounds
If you cannot upgrade now, block SSO sign-in at your application boundary until you can install the fixed release.
Setting providersLimit: 0 prevents new personal-provider registration but does not disable providers that users already registered. If you keep SSO sign-in available, audit existing personal providers and remove any untrusted registrations. If you cannot verify that inventory, registration limits alone are only a partial mitigation.
If you already set resolveUser, the affected sign-in path requires an exact provider match. Upgrading is still the recommended fix.
Technical details
Affected versions found linked accounts by the provider's issuer (the OIDC issuer or SAML entity ID) and the account identifier from the sign-in (the OIDC subject or SAML NameID). The lookup did not also check that the account belonged to the providerId that handled the sign-in.
An attacker could register a personal provider with the same OIDC issuer or SAML entity ID as a legitimate provider. The attacker still controlled the new provider's endpoints or signing keys, so it could assert the subject or NameID of an account linked through the legitimate provider. Because the lookup did not enforce the providerId boundary, Better Auth treated the victim's account as belonging to the attacker's provider and created a session for the victim. The assertion was valid for the attacker's provider, but it did not prove control of the legitimate provider's account namespace.
Version 1.7.3 restores account lookup using both the registered providerId and the asserted account identifier.
Text from GitHub Advisory Database
Affected versions 2
- @better-auth/sso, npm>= 1.7.0-rc.2, < 1.7.0GitHub
- @better-auth/sso, npm>= 1.7.0, < 1.7.3GitHub