Skip to main content

better-auth CVE-2026-53512

| EUVDEUVD-2026-44735 CRITICAL
Improper Authentication (CWE-287)
2026-07-07 https://github.com/better-auth/better-auth GHSA-pw9m-5jxm-xr6h
9.1
CVSS 4.0 · Vendor: https://github.com/better-auth/better-auth
Share

Severity by source

Vendor (https://github.com/better-auth/better-auth) PRIMARY
9.1 CRITICAL
CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
vuln.today AI
7.4 HIGH

AV:N and PR:N because the token endpoint needs no client credentials, but AC:H because exploitation depends on separately obtaining a leaked refresh_token, a precondition outside attacker control; C/I high, A:N.

3.1 AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:H/A:N
4.0 AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N

Primary rating from Vendor (https://github.com/better-auth/better-auth).

CVSS VectorVendor: https://github.com/better-auth/better-auth

CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:H/VI:H/VA:N/SC:N/SI:N/SA:N/E:X/CR:X/IR:X/AR:X/MAV:X/MAC:X/MAT:X/MPR:X/MUI:X/MVC:X/MVI:X/MVA:X/MSC:X/MSI:X/MSA:X/S:X/AU:X/R:X/V:X/RE:X/U:X
Attack Vector
Network
Attack Complexity
Low
Privileges Required
None
User Interaction
None
Scope
X

Lifecycle Timeline

1
Analysis Generated
Jul 07, 2026 - 20:51 vuln.today

Blast Radius

ecosystem impact
† from your stack dependencies † transitive graph · vuln.today resolves 4-path depth
  • 26 npm packages depend on better-auth (19 direct, 7 indirect)

Ecosystem-wide dependent count for version 1.6.11.

DescriptionCVE.org

Am I affected?

Users are affected if all of the following are true:

  • Their application uses better-auth and has enabled at least one of: oidcProvider() (imported from better-auth/plugins/oidc-provider), or mcp() (imported from better-auth/plugins/mcp).
  • Their application has at least one confidential OAuth client registered (any client with type: "web" | "native" | "user-agent-based" in the oauthApplication table, or any trustedClients entry without type: "public"). Public clients with PKCE are not affected.
  • Their application uses better-auth at a version below the patched release.

If an application only uses @better-auth/oauth-provider (the canonical replacement for oidc-provider) and the mcp plugin is not enabled, it is not affected.

Fix:

  1. Upgrade to better-auth@1.6.11 or later.
  2. Migrate from the deprecated oidcProvider() to @better-auth/oauth-provider when feasible. The new package enforces client authentication on both grants by default.
  3. If developers cannot upgrade their applications, see workarounds below.

Summary

The legacy oidcProvider and mcp plugins each expose an OAuth 2.0 token endpoint whose refresh_token grant authenticates the request entirely on possession of the bound refreshToken row and a matching client_id. Neither plugin verifies the registered confidential client's client_secret on the refresh path. An attacker who obtains any valid refresh_token (via database read, log capture, browser-side XSS, or CORS-amplified script in the mcp case) and the public client_id can mint fresh access tokens and rotated refresh tokens until the chain is revoked.

Details

RFC 6749 §6 and OAuth 2.1 §4.3 require confidential clients to authenticate to the token endpoint on every grant, including refresh. The same plugins' authorization_code grant correctly enforces client_secret (the oidc-provider via verifyStoredClientSecret, the mcp plugin via raw equality), which proves the omission on the refresh path is a regression rather than a design choice.

Token rotation issues a new refresh_token with each call, so a single leaked refresh-token grants indefinite access until the row is revoked or its refreshTokenExpiresAt (default 7 days) passes; rotation refreshes that window each call.

Two adjacent issues on the mcp surface ship in the same patch. The mcp authorization_code grant uses raw === for client-secret comparison and ignores the storeClientSecret: "encrypted" | "hashed" configuration; the fix routes both grants through verifyStoredClientSecret. The mcp /mcp/token endpoint sets Access-Control-Allow-Origin: * unconditionally, which amplifies the refresh bypass in browser contexts; the fix narrows the CORS allowlist.

The newer @better-auth/oauth-provider package routes both grants through validateClientCredentials and is not affected.

Patches

Fixed in better-auth@1.6.11. The legacy oidcProvider and mcp token endpoints now require client_secret on the refresh_token grant for confidential clients, using the same constant-time comparison the authorization_code grant already used. Public clients are unaffected (they have no secret to enforce, and PKCE substitutes on the auth-code grant).

The Authorization: Basic parser is fixed to follow RFC 6749 §2.3.1: the credential is split on the first colon and each half is percent-decoded. Client IDs and secrets that contain reserved characters now authenticate correctly. The /mcp/token endpoint's CORS configuration is narrowed in the same change (the wildcard Access-Control-Allow-Origin: * header is removed), matching the standalone @better-auth/oauth-provider package.

The deprecated oidc-provider plugin remains deprecated. The recommended migration path is @better-auth/oauth-provider.

Workarounds

None of these close the bug fully without a code patch.

  • Migrate to @better-auth/oauth-provider if your deployment can adopt the new plugin. It enforces client_secret on both grants.
  • Force all clients to public + PKCE: set every client's type: "public" and require PKCE. The bug is unreachable when there is no client_secret to verify.
  • Network-layer ingress restriction: limit /api/auth/oauth2/token and /api/auth/mcp/token to known client IPs at the load balancer. Practical for server-to-server flows, not for end-user-device clients.
  • Out-of-band refresh-token rotation: on any suspicion of leak, run db.deleteMany({ model: "oauthAccessToken", where: [{ field: "clientId", value: <id> }] }) to invalidate all refresh tokens for the affected client.
  • For the mcp endpoint specifically: drop the wildcard CORS at an upstream proxy and replace with a tight allowlist.

Impact

  • Indefinite confidential-client impersonation: an attacker holding any valid refresh_token and the public client_id can mint access tokens and rotated refresh tokens indefinitely, until the row is revoked. Rotation refreshes the expiration window each call.
  • Resource access at the user's authorized scope: every minted access token carries the original user's authorization scope, so the attacker reads or writes whatever the resource server grants for that scope.

Credit

Reported by @subhanUmer.

Resources

AnalysisAI

Confidential-client impersonation in better-auth below 1.6.11 lets an attacker who holds any leaked refresh_token and the public client_id mint fresh access tokens and rotated refresh tokens indefinitely. The deprecated oidcProvider() and mcp() plugins expose an OAuth 2.0 token endpoint whose refresh_token grant authenticates solely on the bound refresh-token row plus a matching client_id, never verifying the registered client_secret - a regression, since the same plugins' authorization_code grant does enforce the secret. …

Unlock full vulnerability intelligence

  • Risk assessment & exploitation conditions
  • Attack chain visualization
  • Remediation with exact patch versions
  • Threat intelligence from 22 sources
  • Personal watchlist & email alerts

Free forever · No credit card required

Attack ChainAIDerived

Hypothetical attack flow derived from CVE metadata

Access
Obtain leaked refresh_token via log/XSS/DB/CORS
Delivery
Recover public client_id
Exploit
POST refresh_token grant to token endpoint
Execution
Endpoint skips client_secret verification
Persist
Mint access token plus rotated refresh_token
Impact
Access resources at victim's authorized scope

Vulnerability AssessmentAI

Exploitation The target application must run better-auth below 1.6.11 with the oidcProvider() or mcp() plugin enabled AND have at least one confidential OAuth client registered (oauthApplication type "web", "native", or "user-agent-based", or a trustedClients entry not marked type "public"). … Additional conditions and limiting factors are described in the full assessment.
Risk Assessment The supplied CVSS 3.1 vector (AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:N, base 9.1) treats this as trivially exploitable over the network with no privileges, but that overstates real-world ease: the attack is only reachable once the adversary already possesses a valid refresh_token, obtained out-of-band via database read, log capture, browser XSS, or the mcp CORS wildcard. … Full risk analysis with EPSS, KEV, and SSVC signal comparison available after sign-in.
Exploit Scenario An attacker captures a confidential client's refresh_token from an application access log (or, for an mcp deployment, exfiltrates it via injected browser script abetted by the endpoint's wildcard CORS) along with the non-secret client_id. They POST a refresh_token grant to /api/auth/oauth2/token or /api/auth/mcp/token without supplying the client_secret; the endpoint mints a new access token and a rotated refresh token. …
Remediation Vendor-released patch: better-auth@1.6.11 - upgrade to 1.6.11 or later, which requires client_secret on the refresh_token grant for confidential clients using the same constant-time comparison the authorization_code grant already used, routes the mcp authorization_code grant through verifyStoredClientSecret (honoring storeClientSecret), fixes the RFC 6749 §2.3.1 Authorization: Basic parser, and removes the wildcard CORS header from /mcp/token (per https://github.com/better-auth/better-auth/releases/tag/v1.6.11 and advisory GHSA-pw9m-5jxm-xr6h). … Detailed patch versions, workarounds, and compensating controls in full report.

Recommended ActionAI

Within 24 hours: Audit all deployed instances of better-auth to identify versions below 1.6.11 and verify whether oidcProvider() or mcp() plugins are enabled. …

Sign in for detailed remediation steps and compensating controls.

Threat intelligence, references, and detailed analysis are available after sign-in.

CVE-2012-0217 HIGH POC
7.2 Jun 12

The x86-64 kernel system-call functionality in Xen 4.1.2 and earlier, as used in Citrix XenServer 6.0.2 and earlier and

CVE-2026-33309 CRITICAL POC
9.9 Mar 19

An authenticated path traversal vulnerability in Langflow's file upload functionality allows attackers to write arbitrar

CVE-2019-7304 CRITICAL POC
9.8 Apr 23

Canonical snapd before version 2.37.1 incorrectly performed socket owner validation, allowing an attacker to run arbitra

CVE-2026-33186 CRITICAL POC
9.1 Mar 18

An authorization bypass vulnerability in gRPC-Go allows attackers to circumvent path-based access control by sending HTT

CVE-2026-50180 HIGH POC
8.7 Jul 02

Arbitrary file read in Langroid's SQLChatAgent (<= 0.63.0) lets an attacker who can influence the LLM-generated SQL exfi

CVE-2020-14966 HIGH POC
7.5 Jun 22

An issue was discovered in the jsrsasign package through 8.0.18 for Node.js. Rated high severity (CVSS 7.5), this vulner

CVE-2020-13822 HIGH POC
7.7 Jun 04

The Elliptic package 6.5.2 for Node.js allows ECDSA signature malleability via variations in encoding, leading '\0' byte

CVE-2026-29181 HIGH POC
7.5 Apr 07

Resource exhaustion in OpenTelemetry Go propagation library (v1.41.0 and earlier) enables remote attackers to trigger se

CVE-2019-7303 HIGH POC
7.5 Apr 23

A vulnerability in the seccomp filters of Canonical snapd before version 2.37.4 allows a strict mode snap to insert char

CVE-2014-4699 MEDIUM POC
6.9 Jul 09

The Linux kernel before 3.15.4 on Intel processors does not properly restrict use of a non-canonical value for the saved

CVE-2017-7725 MEDIUM POC
6.1 Apr 13

concrete5 8.1.0 places incorrect trust in the HTTP Host header during caching, if the administrator did not define a "ca

CVE-2026-48816 MEDIUM POC
6.5 Jul 01

Timestamp forgery in sigstore-js allows an attacker supplying a crafted bundle v0.2 to manipulate certificate validity w

Share

CVE-2026-53512 vulnerability details – vuln.today

This site uses cookies essential for authentication and security. No tracking or analytics cookies are used. Privacy Policy