Skip to content
← Blog · · df00tech

Better Auth: OAuth Sign-In State Can Be Replayed as a Magic Link to Hijack Any Account

breaking ghsa npm CVE-2026-114607

What happened

A GitHub Security Advisory (GHSA-965c-763c-88jm, tracked as CVE-2026-114607, CVSS 9.1) reports that better-auth versions from 1.4.0-beta.18 up to but not including 1.7.7 can accept an OAuth sign-in state value as a valid Magic Link token. According to the advisory, an attacker can start an OAuth sign-in with any target email address. They then take the returned state value and redeem it as a Magic Link to finish authentication for that address. They never read the victim's inbox and never complete the OAuth callback. The advisory lists the exploit status as public PoC.

Affected setups require all of the following: Magic Link enabled with the default or compatible storeToken and storeIdentifier settings, at least one social or Generic OAuth provider enabled, and account.storeStateStrategy set to "database". Database state is the default when a database or secondary storage is configured. Cookie-backed state is not vulnerable to this path, though the advisory flags a separate OAuth Proxy caveat.

Why it matters

This is an unauthenticated account-takeover issue for applications using better-auth with the affected combination. The attacker needs only a known email address. No credentials, no mailbox access, and no OAuth provider interaction beyond starting the flow. Per the advisory, if Magic Link sign-up is also enabled and no account exists for that email, an attacker can create a new account that Better Auth wrongly marks as email-verified and is signed in to it. That false flag can also bypass Better Auth's default unproven-account protections when the real mailbox owner later signs in, leaving the attacker's session in the account. Any application that trusts verified-email status or email domain for authorization is at higher risk.

Who is affected

  • Any npm project depending on better-auth in the vulnerable version range
  • Deployments with Magic Link plus social or Generic OAuth plus database-backed OAuth state, which is the default when a database or secondary storage is configured
  • Multi-server deployments sharing verification storage

What defenders should do now

  • Inventory exposure: check whether your better-auth version falls in 1.4.0-beta.18 through <1.7.7 and whether Magic Link and social or Generic OAuth are both enabled with storeStateStrategy: "database".
  • Apply workarounds now. The fix is merged but 1.7.7 is not yet released. Set account.storeStateStrategy to "cookie" (note the separate OAuth Proxy secret caveat if you use OAuth Proxy), or set Magic Link's storeToken to "hashed" while leaving verification.storeIdentifier unset or "plain", or temporarily disable Magic Link or OAuth sign-in.
  • Hunting angle: look for OAuth sign-in starts followed quickly by Magic Link verification completions for the same account or email, especially where no matching OAuth callback from the provider occurred.
  • Post-upgrade hygiene: once patched, request new Magic Links and restart pending OAuth or SAML sign-ins. The advisory states that links and state created before the upgrade cannot complete. Review accounts marked email-verified via Magic Link or OAuth flows during the exposure window for signs of illegitimate creation or takeover.
  • Note: disableSignUp: true on the Magic Link plugin is called out as insufficient. It blocks new verified-account creation but does not stop takeover of existing accounts.

Developing intel

This is a same-day advisory. The fix is merged but not yet shipped in a released better-auth package, so details, patch availability, and workaround guidance may change. Track the original advisory for the latest status: GHSA-965c-763c-88jm.

Get new detections in your inbox

New ATT&CK coverage plus CISA KEV / CVE detection rules, roughly weekly. No spam, unsubscribe anytime.