# Better Auth has an account takeover issue via OAuth auto-link to unverified pre-registered email

Better Auth auto-linked OAuth identities to pre-registered unverified local emails, letting an attacker who signed up with a victim's email gain persistent account takeover.

- Payout: Research
- Severity: high
- Program: Better Auth
- Found by: avrmeduard
- Disclosed: 2026-07-07
- CVE: CVE-2026-53516
- Write-up quality: 7/10
- Original: https://github.com/advisories/GHSA-g38m-r43w-p2q7
- Library page: https://bugbountylibrary.com/r/ghsa%3AGHSA-g38m-r43w-p2q7
- Tags: area:web domain:web impact:ato kind:research platform:ghsa sev:high tech:oauth tech:oidc tech:sso technique:source-review vuln:access-control vuln:account-takeover vuln:auth-bypass

**Target:** OAuth/SSO callback handler (handleOAuthUserInfo) in better-auth npm package
**Root cause:** The implicit account-linking gate in handleOAuthUserInfo only checks the provider's emailVerified claim and never reads the local user row's emailVerified flag, so a pre-registered unverified row at the victim's email is matched and linked.
**Steps:**
1. Attacker calls `/sign-up/email` with the victim's email, creating a local row with `emailVerified: false` and an attacker-known password.
2. Victim later signs in via any configured OAuth/SSO provider whose `email_verified` claim is true.
3. No `(accountId, providerId)` match exists, so lookup falls back to email and surfaces the attacker's pre-registered row.
4. Auto-link gate admits the link because only the provider claim is checked; post-link step flips local `emailVerified` to true.
5. Attacker logs in with the password they set, now on a verified account that also holds the victim's OAuth identity.
**How found:** Code reading of the auto-link gate: noticed it validated only the provider's emailVerified claim and never the local row's flag, then traced the email-fallback lookup and the post-link verification flip to confirm the pre-hijack chain.
**Exploitation:** Precondition: app has emailAndPassword enabled, an OAuth/SSO provider, and implicit linking not disabled. Attacker pre-registers the victim's email via `/sign-up/email`, waits for the victim to authenticate via OAuth, then uses their own password to access the now-linked, verified account holding the victim's OAuth identity.
**Escalation:** The link-time emailVerified flip defeats `requireEmailVerification: true`, and the same primitive reaches every path calling handleOAuthUserInfo (social, generic-oauth, oauth-proxy, SSO OIDC/SAML, one-tap).
**Insight:** In pre-account-hijacking, check whether the linking gate trusts only the IdP's email_verified claim; if the local row's emailVerified is never read, an attacker-registered unverified row at the victim's email becomes the link target, and any post-link verification flip turns it into a working password login.

