Better Auth accepted an OAuth sign-in state as a Magic Link token, so knowing a user's email was enough to sign in as them
On October 22, 2026, CVE-2026-114607 was published for better-auth from 1.4.0-beta.18 until 1.7.7. In apps that enable Magic Link and a social or Generic OAuth provider with database-backed OAuth state, an OAuth sign-in state value could be redeemed as a Magic Link token. An unauthenticated attacker who knew a user's email address could get a session as that user without access to the mailbox. The record scores it CVSS 3.1 9.1 Critical. The fix is in 1.7.7, and the advisory was published September 30, 2026.
What was reported
CVE-2026-114607 was published October 22, 2026. The record, from GitHub, covers better-auth from 1.4.0-beta.18 until 1.7.7. It says deployments that enable Magic Link with storeToken set to plain, or with storeToken set to hashed and the global verification.storeIdentifier setting also set to hashed, that enable a built-in social or Generic OAuth provider, and that use account.storeStateStrategy set to database can accept an OAuth sign-in state value as a Magic Link token. An unauthenticated attacker can start an OAuth sign-in for a known email address and redeem the returned state through Magic Link, without controlling the mailbox or completing the provider callback. The attacker gets a normal session for the existing user, or, when sign-up is enabled, an account wrongly marked as email verified. The record names CWE-287 and scores it CVSS 3.1 9.1 Critical. NVD carries the same description.
Better Auth's advisory, GHSA-965c-763c-88jm, was published September 30, 2026. It says storeToken: "plain" is the Magic Link default, and that database-backed OAuth state is the default when a database or secondary storage is configured. Cookie-backed state blocks this path. The advisory says to keep Better Auth adapters, plugins, and integrations on the same release as the core package, and that Magic Links and OAuth sign-ins started before the upgrade will not complete.
Until an app can move to 1.7.7, the advisory's workarounds are to set account.storeStateStrategy to "cookie", to set the Magic Link storeToken to "hashed" while leaving the global verification.storeIdentifier unset or "plain", or to turn off Magic Link or social and Generic OAuth sign-in. Apps using OAuth Proxy should give the proxy its own secret, different from the global Better Auth secret, before switching to cookie state. The advisory also says that setting disableSignUp: true on the Magic Link plugin is not enough, because it only stops new verified accounts from being created.
How to prevent it
Upgrade better-auth to 1.7.7 or later, and move the Better Auth plugins and adapters you use to the same release. If you cannot upgrade today, turn off Magic Link or social sign-in until you can. Setting disableSignUp on the Magic Link plugin does not stop the takeover of existing accounts.
Sources
Related
Incidents on the same topics
- A crafted URL could run PowerShell on Windows through the open package, and MCP Inspector and OpenCode were affected
- Google's Cloud Run MCP server could send your source code to a storage bucket an attacker set up first
- One compressed request can crash a Node.js app that uses body-parser with default options
- @sentry/nextjs tunnelRoute skipped Next.js middleware for more paths than it forwards to Sentry
Guides for the same stack
The weekly fix
The weekly fix: 3 real security mistakes in vibe-coded apps and how to fix them, every Tuesday.