Users are affected if all of the following are true:
@better-auth/sso at a version >= 0.1.0, < 1.6.11 on the stable line, or any 1.7.0-beta.x on the pre-release line.sso() plugin is added to their application's betterAuth({ plugins: [...] }) array.POST /sso/register (the plugin's default gate accepts any session).For the non-blind SSRF impact (full IAM credential or internal HTTP body exfiltration), no further configuration is required.
For the account takeover escalation, additionally:
sso({ trustEmailVerified: true, ... }).email overlaps with attacker-chosen domains.If developers do not enable the SSO plugin, their application is not affected.
Fix:
@better-auth/sso@1.6.11 or later.The @better-auth/sso plugin's POST /sso/register endpoint accepts attacker-controlled oidcConfig.userInfoEndpoint, tokenEndpoint, and jwksEndpoint URLs when skipDiscovery: true is set, persists them on the ssoProvider row without origin validation, then issues server-side fetches to those URLs during the OIDC callback. The fetched response body is reflected through the user profile, producing a non-blind SSRF reachable by any authenticated session. The same primitive exists on POST /sso/update-provider.
The schema field types accept bare strings: no .url() validator, no origin gate. The discovery branch (skipDiscovery: false) routes URLs through validateDiscoveryUrl; the skip-discovery branch persists them as-is. At callback time three fetch sites read the stored URLs: validateAuthorizationCode for the token endpoint, betterFetch for the userInfo endpoint, and validateToken for the JWKS endpoint.
When trustEmailVerified: true is configured, the...
1.6.11Exploitability
AV:NAC:LPR:LUI:NScope
S:CImpact
C:HI:HA:N9.6/CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:N