better-auth — 13+ OAuth/OIDC/SSO/SCIM advisories including a critical MCP-plugin refresh-token bypass (CVE-2026-53512)
TL;DR
better-auth — a widely-adopted TypeScript auth library commonly paired with Next.js and Supabase-style "vibe coded" stacks as an alternative to NextAuth.js/Auth.js — published 13 security advisories on 2026-06-02 (2 critical, 9 high, 1 medium, 1 low) and 4 more on 2026-06-26, spanning account takeover via SSO/SAML/OIDC, SCIM provider-ID collisions, magic-link/OTP pre-account hijacking, cross-organization billing tampering, and OAuth refresh-token flaws. The most severe for AI-tool users: CVE-2026-53512 (CVSS 9.1, critical) — the deprecated oidcProvider and mcp plugins issue OAuth refresh tokens without verifying the client's secret, so anyone who obtains a valid refresh token (via log capture, DB read, or XSS) can mint fresh access tokens indefinitely. Update to better-auth ≥ 1.6.11 (≥ 1.6.22 for the SCIM plugin); the mcp and oidcProvider plugins are deprecated and slated for removal in 1.7 — better-auth's own guidance is to migrate off them rather than keep patching.
What happened
better-auth positions itself as a framework-agnostic, TypeScript-first alternative to NextAuth.js/Auth.js, and ships a plugin architecture covering SSO, SAML, OIDC, SCIM provisioning, Stripe billing, and — relevant to AI coding agents — an MCP (Model Context Protocol) OAuth-provider plugin for authenticating MCP clients. It runs a formal internal security-review process (triage → code review → scanning → patch review → advisory), which is how this batch surfaced.
2026-06-02 batch (13 advisories, 2 critical + 9 high): covers issues across @better-auth/sso, @better-auth/oauth-provider, and the deprecated oidcProvider/mcp plugins. The standout for this repo's audience:
- CVE-2026-53512 (critical, CVSS 9.1) — the deprecated
oidcProviderandmcpplugins each expose an OAuth 2.0 token endpoint whoserefresh_tokengrant authenticates purely on possession of the bound refresh-token database row plus a matching (public, non-secret)client_id— the plugin never verifies the confidential client'sclient_secreton the refresh path. Anyone who obtains a valid refresh token — via a database read, a log line, browser-side XSS, or (specific to themcpplugin) a CORS-amplified script — can mint fresh access tokens and rotated refresh tokens indefinitely, until the token chain is explicitly revoked. This directly affects any app that stood up better-auth's MCP OAuth provider to authenticate MCP clients. Fixed in 1.6.11. - GHSA-p2fr-6hmx-4528 (moderate) —
@better-auth/oauth-provideraccess tokens aren't audience-bound to the authorization grant (RFC 8707), letting a token issued for one resource be replayed against another. - GHSA-392p-2q2v-4372 / GHSA-7w99-5wm4-3g79 (high) — OAuth refresh-token rotation race conditions that fork the token family or allow concurrent redemption, undermining rotation-based revocation.
- GHSA-86j7-9j95-vpqj (moderate) — stored XSS in the deprecated
oidc-provider's auth-server origin via ajavascript:redirect URI.
2026-06-26 batch (4 more advisories): extends the same theme —
- GHSA-rjg6-39jm-rgg4 (critical, CVSS 9.9) —
@better-auth/scimused the same logical provider ID for SCIM configuration and account ownership, letting an authenticated user mint a SCIM token that matches an existing SSO/SAML/OIDC/social provider ID and act through a provider namespace they don't own; also missing SCIM-activedeactivation modeling and email-uniqueness checks on update. Fixed in 1.6.22 / 1.7.0-beta.10. - GHSA-qq9h-g4jm-xgf3 (high) — account takeover via pre-account hijacking on magic-link and email-OTP sign-in.
- GHSA-prpr-5gj3-qqhg (high) — account takeover via multiple SSO flaws.
- GHSA-h3rm-78g3-j7cp (high) —
@better-auth/stripecross-organization billing tampering in organization-subscription actions.
Vendor guidance: better-auth's own June 2026 security-update post recommends updating to the latest 1.6.x release (1.6.14 at time of posting) for both the core package and any scoped plugin packages in use, and explicitly recommends migrating off the deprecated oidcProvider and mcp plugins to @better-auth/oauth-provider rather than continuing to rely on patches to legacy code slated for removal in 1.7.
Am I affected?
# Check installed version
npm ls better-auth 2>/dev/null
cat package.json | grep -A2 '"better-auth"'
# Check whether you use the deprecated MCP or OIDC provider plugins
grep -rE "oidcProvider|mcp\(\)|@better-auth/(sso|scim|stripe|oauth-provider)" src/ 2>/dev/null
You are affected if you run better-auth < 1.6.11 (core OAuth/OIDC issues), @better-auth/scim < 1.6.22 (SCIM collision), or use the deprecated oidcProvider/mcp plugins at all — those are being removed in 1.7 and should be migrated off regardless of patch status.
IOCs
| Type | Value |
|---|---|
| Critical CVE | CVE-2026-53512 — MCP/OIDC refresh-token client-secret bypass, CVSS 9.1 |
| Critical GHSA | GHSA-rjg6-39jm-rgg4 — SCIM provider-ID collision, CVSS 9.9 |
| Affected | better-auth < 1.6.11 (core); @better-auth/scim < 1.6.22 |
| Fixed | better-auth ≥ 1.6.11; @better-auth/scim ≥ 1.6.22 |
| Deprecated, migrate off | oidcProvider and mcp plugins (removed in 1.7) |
| Total advisories | 13 (2026-06-02) + 4 (2026-06-26) |
Update — 2026-07-18: two more @better-auth/sso CVEs, published the same day, fixed in the same 1.6.11 you should already be on
Two additional CVEs in @better-auth/sso were published on 2026-07-15 — both patched in the same 1.6.11 release already recommended above, so anyone who updated in response to CVE-2026-53512 is already fixed, but anyone still on an older build has more exposure than previously documented here:
- CVE-2026-53513 (GHSA-5rr4-8452-hf4v, CVSS 9.6, critical) — the
POST /sso/registerendpoint accepts attacker-controlledoidcConfig.userInfoEndpoint,tokenEndpoint, andjwksEndpointURLs whenskipDiscovery: trueis set, persists them on thessoProviderrow with no origin validation, then issues server-side fetches to those URLs during the OIDC callback and reflects the response body back through the user profile — a non-blind SSRF reachable by any authenticated session. This reaches internal-only endpoints: cloud metadata services (AWS IMDS), Redis, admin panels bound to localhost. Worse, iftrustEmailVerified: trueis configured (a common convenience setting), a crafteduserInforesponse withemailVerified: trueand an attacker-chosen email triggers OAuth auto-linking against any pre-existing account with that email — turning the SSRF into full account takeover. Mitigate immediately by settingsso({ providersLimit: 0 })to block self-registration, gating/sso/registerat your reverse proxy, and settingtrustEmailVerified: false. - CVE-2026-53515 (GHSA-gv74-j8m3-fg5f, CVSS 7.1, high) — from
1.2.10until1.6.11,registerSSOProviderchecked only for organization-membership when handlingPOST /sso/register, not an owner/admin role — any organization member could attach an attacker-controlled OIDC/SAML provider to the organization, which then drives/sso/callback/{providerId}provisioning for that org.
Both are fixed in better-auth ≥ 1.6.11, same as CVE-2026-53512. If you already updated for the June batch, you're covered; if not, these two raise the urgency — CVE-2026-53513 in particular is a higher CVSS than the original headline CVE.
Update — 2026-07-23: two more CVE numbers assigned to items already in this batch
Two items from the original 2026-06-02 disclosure that were previously tracked here only by GHSA ID have now had CVE numbers assigned — no new vulnerability, just canonical IDs for context already covered above:
- CVE-2026-45337 (GHSA-cq3f-vc6p-68fh, high) — the
deviceAuthorizationplugin's device-flow endpoints treated any authenticated session as the owner of a pending device code:GET /devicenever claimed the row, andPOST /device/approve/POST /device/denysilently accepted any caller when the row'suserIdwas unset. An authenticated attacker who learned a validuser_codebefore the legitimate user finished approving could bind the polling device to their own account (account takeover) or deny the legitimate sign-in. Fixed in 1.6.11 —GET /devicenow claims the row for the calling session, and approve/deny require strict owner equality. - CVE-2026-53516 (GHSA-g38m-r43w-p2q7, this repo's ID for the pre-account-hijacking item referenced above) — the OAuth callback's auto-link gate in
handleOAuthUserInfoimplicitly links an incoming OAuth identity to an existing local account whenever the provider assertsemail_verified: true, without also checking that the local account's ownemailVerifiedflag is true. An attacker who pre-registers an unverified account at the victim's email address, then waits for the victim to sign in via Google/GitHub/SSO, gets their OAuth identity silently attached to the attacker-controlled row — full persistent account takeover, andrequireEmailVerification: truedoes not mitigate it. Fixed in 1.6.11: implicit linking now refuses to attach an OAuth identity to a local account withemailVerified: false.
No new update action required beyond what's already recommended below — both are covered by the same better-auth ≥ 1.6.11 upgrade.
If you are affected
- Update
better-authand every scoped plugin package you use to the versions above. - If you use the
mcporoidcProviderplugins to authenticate MCP clients, migrate to@better-auth/oauth-provider— these plugins are deprecated and won't receive further security attention beyond 1.7 removal. - Revoke and rotate all outstanding refresh tokens issued by an affected instance if you were on a pre-1.6.11 build and can't rule out token exposure (logs, DB access, XSS reports).
- Audit SCIM-provisioned accounts for provider-ID collisions if you run
@better-auth/scimpre-1.6.22 — look for SCIM-provisioned users that unexpectedly share identifiers with SSO/SAML/OIDC/social-login accounts. - See playbooks/rotating-cloud-credentials.md.
Prevention
- Treat auth-library plugin architectures the same as any other dependency surface — audit which plugins you actually use, and remove ones you don't (each additional plugin, especially a deprecated one, is additional attack surface with a shrinking patch commitment).
- When wiring MCP OAuth into any auth library, verify the token endpoint enforces
client_secret(or PKCE for public clients) on every grant type, not just the initial authorization — refresh-token grants are a common place for this check to be silently dropped. - → prevention/credential-hygiene.md
Sources
- better-auth — Security update: June 2026 — vendor's own disclosure post; 13 advisories, severity breakdown, migration guidance for
oidcProvider/mcp. - GitHub — better-auth/better-auth security advisories — full advisory index with GHSA IDs and severities.
- GitLab Advisory Database — CVE-2026-53512 — canonical CVE record for the MCP/OIDC refresh-token bypass; CVSS 9.1, CWE-287/306/345/863, fixed version 1.6.11.
- GitHub Security Advisory — GHSA-rjg6-39jm-rgg4 — SCIM provider-ID collision advisory; affected/fixed versions, disclosure date 2026-06-26.
- GitHub Security Advisory — GHSA-5rr4-8452-hf4v (CVE-2026-53513) —
@better-auth/ssoSSRF via unvalidated OIDC endpoints on provider registration; vendor advisory, CVSS 9.6. - GitLab Advisory Database — CVE-2026-53513 — independent corroboration of the SSRF advisory.
- Security Online — Better Auth SSRF Flaw CVE-2026-53513 (CVSS 9.6) Threatens 19M-Download Auth Library — independent write-up with attack-chain detail (SSRF → account takeover via
trustEmailVerified). - GitLab Advisory Database — CVE-2026-45337 — canonical CVE record for the device-authorization owner-binding bug.
- GitHub Security Advisory — GHSA-cq3f-vc6p-68fh (CVE-2026-45337) — vendor advisory, fetched directly.
- GitLab Advisory Database — CVE-2026-53516 — canonical CVE record for the OAuth pre-account-hijacking bug.
- better-auth — Security update: June 2026 — vendor's own post listing both GHSA IDs (GHSA-cq3f-vc6p-68fh, GHSA-g38m-r43w-p2q7) alongside the rest of the June batch; fetched directly to confirm both were part of the already-disclosed batch, not new vulnerabilities.