Authenticate as One Client, Authorize as Another: OAuthLib CVE-2026-118669 Turns Scope Checks Into Suggestions
OAuth put two jobs on the token endpoint — prove who you are, then decide what you may have — and trusted the library to keep the answers attached to the same party. CVE-2026-118669, published to NVD on 28 October 2026 and assessed at CVSS 9.6 in the GitLab Advisory Database, breaks that assumption in OAuthLib before 4.0.0: in the client_credentials and Resource Owner Password Credentials grant handlers, the library authenticates one client and then authorizes the grant using a different, attacker-supplied client_id taken from the request body. A low-privilege confidential client can therefore walk out with tokens carrying another client’s grants and scopes. If your agent stack runs its own OAuth token endpoint on OAuthLib — and a growing number of MCP deployments do exactly that — this is a patch-now finding.
One request, two identities
The mechanism, per the upstream advisory GHSA-7984-qgvg-3j9c, is a three-line tragedy in the request lifecycle. OAuthLib’s Request object parses query and body parameters into attributes, including client_id. Then authenticate_client(request) runs the integrator’s own authentication and sets request.client to the authenticated client object — but nothing requires request.client_id to match request.client.client_id. If the body already contains client_id=..., that value survives, and it is the body value — not the authenticated object — that gets passed to validate_grant_type() and validate_scopes(). So an attacker with credentials for one valid low-privilege client authenticates as itself, names a broader client in the body, and the grant and scope checks run under the victim’s identity. The issue bites precisely where integrators follow the documented API and consume the client_id argument; deployments whose validators ignore that argument and authorize exclusively from request.client are, per the advisory, likely unaffected. The fix in 4.0.0 (commit c951a1d, PR 920) closes the split. Note the CVSS vector — AV:N/AC:L/PR:L/UI:N/S:C — network-reachable, no user interaction, scope changed: the attacker only needs to already hold some client credential, the exact thing a multi-tenant agent platform hands out routinely.
Why this is an agent-stack CVE
OAuthLib is plumbing — it ships inside countless Python services, which is why this CVE matters beyond whoever runs an OAuth server on purpose. Dependency scanners have already started flagging MCP packages that bundle it: Threat Radar records name mcp-google-sheets (via google-auth-oauthlib) and mcp-atlassian among the dependents, and the flag is worth precisely one careful distinction. Client-side use of the library — asking Google for a token — is not the affected surface; the flaw lives in provider-side token-grant handling. The exposure that counts is any MCP server or agent gateway that implements its own OAuth authorization server on OAuthLib and validates grants the documented way. That population has been growing all year: our mcp-atlassian file-exfiltration briefing and the MCP TypeScript SDK’s audience-blindness batch both show identity checks as the layer MCP implementations get wrong most often — and the AWS API MCP server’s own audience-validation bypass, briefed alongside this post, is the same bug family wearing a vendor badge. Audit the token endpoint, not just the dependency tree.
What to do
- Upgrade OAuthLib to 4.0.0 everywhere it can act as a provider. Client-only bundles can follow normal patch cadence; anything serving a token endpoint goes first.
- Find your token endpoints. Inventory every service in the agent stack that issues OAuth tokens — MCP servers with built-in auth, gateways, proxies — and check which library serves the grant handlers.
- Authorize from
request.client, not theclient_idargument. Even patched, treating the authenticated object as the single source of identity removes the whole class. - Assume issued tokens are suspect until rotated. Any token minted through a vulnerable endpoint while a low-privilege client existed in the same deployment should be revoked and reissued after patching.
Sources:
- NVD — CVE-2026-118669 (published 28 October 2026; description and references read first-hand)
- oauthlib/oauthlib — GHSA-7984-qgvg-3j9c (affected surface, validator contract, fix in 4.0.0; read first-hand)
- GitLab Advisory Database — CVE-2026-118669 (CVSS 9.6 assessment, affected/fixed versions; read first-hand)
- Threat Radar — downstream dependency flags including MCP packages (scanner-match evidence; cited by URL)