Better Auth OAuth Refresh Token Replay via Missing Client Authentication (CVE-2026-53512)
The legacy `oidcProvider` and `mcp` plugins in the `better-auth` library versions prior to 1.6.11 are vulnerable to CVE-2026-53512, an OAuth refresh-token replay attack where the plugins fail to verify the `client_secret` of confidential clients during the `refresh_token` grant, allowing an attacker who obtains a valid `refresh_token` and `client_id` to indefinitely mint new access tokens and impersonate the client for unauthorized resource access.
A critical vulnerability, CVE-2026-53512, has been identified in the better-auth library, affecting applications using the deprecated oidcProvider() or mcp() plugins in versions prior to 1.6.11. This flaw stems from a missing client authentication step during the OAuth 2.0 refresh_token grant for confidential clients. Unlike the authorization_code grant, these plugins failed to verify the client_secret, enabling an attacker to replay a stolen refresh_token and its corresponding public client_id to repeatedly mint new access tokens. The attacker can gain indefinite access to resources with the user's original authorized scope, as token rotation refreshes the expiration window with each call. This significantly impacts any better-auth application configured with confidential OAuth clients using the vulnerable plugins.
Attack Chain
- Initial Access / Credential Acquisition: An attacker obtains a valid
refresh_tokenand the associated publicclient_idfor a confidential OAuth client. This could occur through various methods such as a database breach, log file capture, browser-side Cross-Site Scripting (XSS), or via a CORS-amplified script if exploiting themcpendpoint with its wildcardAccess-Control-Allow-Origin: *. - Exploitation of Missing Authentication: The attacker sends a
POSTrequest to the vulnerable OAuth 2.0 token endpoint (e.g.,/api/auth/oauth2/tokenor/api/auth/mcp/token) using the stolenrefresh_tokenandclient_id, but crucially, without providing theclient_secret. - Token Endpoint Bypass: Due to the flaw in
better-authversions prior to 1.6.11, theoidcProviderormcpplugins do not enforceclient_secretverification on therefresh_tokengrant for confidential clients, allowing the unauthenticated request to proceed. - Access Token Minting: The vulnerable token endpoint issues a new, valid
access_tokento the attacker, along with a rotatedrefresh_token. - Indefinite Session Prolongation: The attacker uses the newly minted
refresh_tokento repeat steps 2-4, effectively resetting the expiration window of the session and gaining indefinite access. - Resource Access: With the valid
access_token, the attacker can impersonate the legitimate client and user, making requests to resource servers to access, modify, or exfiltrate data within the scope of the original user's authorization.
Impact
The impact of CVE-2026-53512 is significant, primarily leading to indefinite confidential-client impersonation. An attacker who has acquired a single refresh_token and the corresponding client_id can continuously mint new access_tokens and rotate refresh_tokens, thereby maintaining persistent unauthorized access without further authentication. Each newly issued access_token carries the original user's authorized scope, granting the attacker the ability to read, write, or otherwise manipulate data on resource servers as if they were the legitimate user. This can result in severe data breaches, unauthorized modifications, and complete compromise of data governed by the affected OAuth client's permissions. The vulnerability affects better-auth applications leveraging the deprecated oidcProvider or mcp plugins.
Recommendation
- Upgrade immediately to
better-auth@1.6.11or later to apply the official patch for CVE-2026-53512. - Migrate from deprecated plugins by transitioning from
oidcProvider()to the canonical@better-auth/oauth-providerpackage, as it enforces client authentication on all grants by default. - Implement network-layer ingress restriction for
/api/auth/oauth2/tokenand/api/auth/mcp/tokenendpoints to known client IPs at the load balancer, which can partially mitigate risk for server-to-server flows. - Force all clients to public + PKCE by setting every client's
type: "public"and requiring PKCE, thereby eliminating theclient_secretfor verification where the bug manifests. - For the mcp endpoint specifically, drop the wildcard CORS header at an upstream proxy and replace it with a tight allowlist to prevent CORS-amplified attacks.