GHSA-g38m-r43w-p2q7: Better Auth has an account takeover issue via OAuth auto-link to unverified pre-registered email
Am I affected?
Users are affected if all of the following are true:
- Their application uses better-auth at a version < 1.6.11 on the stable line, or any current next pre-release.
- emailAndPassword.enabled: true is set in their application's betterAuth({ ... }) configuration.
- At least one OAuth or SSO provider is configured (any built-in social provider, or genericOAuth(...), or any provider via @better-auth/sso).
- account.accountLinking.disableImplicitLinking is not set to true.
- account.accountLinking.enabled is not set to false.
Setting either disableImplicitLinking: true or enabled: false closes the hole at the cost of breaking the standard "add another login method" UX. emailAndPassword.requireEmailVerification: true does not mitigate, because the link-time emailVerified flip promotes the attacker's row to verified, after which the password login becomes usable.
Fix:
1. Upgrade to better-auth@1.6.11 or later.
2. If developers cannot upgrade, see workarounds below.
Summary
The OAuth callback's auto-link gate in handleOAuthUserInfo admits an implicit account link whenever the provider asserts email_verified: true, without requiring the local user row's emailVerified to also be true. An attacker who pre-registers a victim's email through /sign-up/email (which writes a row with emailVerified: false) can have the victim's later OAuth identity bound to the attacker's user row, granting both a password login and the victim's OAuth identity on the same account. This is the pre-account-hijacking class — the same shape as Microsoft "nOAuth" (2023) and the Sign in with Apple JWT flaw (2020).
Details
The auto-link gate validates only the OAuth provider's userInfo.emailVerified claim. The local row's emailVerified field is never read. When no (accountId, providerId) match exists, the user lookup falls back to email, which surfaces any pre-registered row at that email.
A separate post-link step promotes the local emailVerified to true when the provider's claim
Details
Original advisory: https://github.com/advisories/GHSA-g38m-r43w-p2q7
Referenced CVEs
| CVE | CSIRTS overview | External |
|---|---|---|
| CVE-2026-53516 | coverage & exploitation status | NVD · CVE.org |
More from GitHub Security Advisories
- criticalGHSA-g936-7jqj-mwv8: TSDProxy: Internal proxy auth token forwarded to backend services enables management API …2026-07-10
- highGHSA-fpg8-7664-jc5q: melange: Incomplete package integrity verification allows data section substitution2026-07-10
- mediumGHSA-48rx-c7pg-q66r: Excon does not redact additional sensitive/risky headers when following redirects2026-07-10
- highGHSA-h4g2-xfmw-q2c9: Clauster: Non-loopback deployments can serve the dashboard unauthenticated when auth.enab…2026-07-10
- mediumGHSA-rqq5-2gf9-4w4q: Secure Headers: CSP directive injection via sandbox, plugin_types, and report_to when giv…2026-07-10