A flaw in the official MCP Python SDK let hostile servers walk off with OAuth logins
Applications built on Anthropic's Model Context Protocol client library could be tricked into sending real service credentials to an attacker-controlled endpoint. The fix is in version 1.30.0.

Key points
- The Model Context Protocol Python SDK, the official library used to build applications that talk to MCP servers, had a flaw that let a hostile server harvest the OAuth login credentials the application uses for real services, per the maintainers' advisory GHSA-qx49-fqc8-xw99.
- The fix ships in version 1.30.0; anything earlier that uses the SDK's HTTP OAuth client is exposed.
- Stolen material can include the client secret, the authorization code and the PKCE code_verifier, meaning an attacker can complete the login as if they were the victim application.
- The bug lives in the client-side auth code, so patching an MCP server does nothing: the software calling the server is what needs updating.
- Threat Vectr's own tracking of MCP-related disclosures shows this is the first credential-theft class bug in the reference SDK itself, rather than in a third-party connector.
The Model Context Protocol, or MCP, is the plumbing a growing number of AI assistants use to reach outside tools: your calendar, your GitHub, your company's ticketing system. Anthropic published the reference client library in Python, and a lot of shipping product depends on it.
That library had a hole. A malicious or hijacked MCP server could point the client at a login endpoint of the attacker's choosing, and the client would happily send along the secrets meant for the legitimate service.
What actually went wrong?
The SDK let the server on the other end of the wire decide where the client's OAuth credentials got sent. OAuth is the standard "log in with" handshake that lets one app act on your behalf inside another. In a healthy setup the client should only ever talk to the authorization server it was registered with, for example Google's or GitHub's login endpoint.
The SDK did not check that. According to the maintainers' writeup, the issuer field in the server's metadata was not validated on every discovery path, and stored client credentials were not bound to the authorization server they belonged to. A hostile MCP server could publish metadata naming its own token endpoint, or lie and claim the user's real login provider as the issuer while pointing the actual traffic elsewhere. Either way the client_secret, the authorization code and the PKCE code_verifier (the one-time proof that ties a login request to the app that started it) landed in attacker hands.
With those three, an attacker can finish the login flow against the real service and get access tokens for the victim's account.
Who is exposed?
You are affected if your application uses the Python SDK as an MCP client over HTTP, with one of the shipped OAuth providers (OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider, or the deprecated 1.x RFC7523OAuthClientProvider), and it can be pointed at an MCP server you do not fully control.
In practice that covers most "connect this AI agent to any MCP tool" products built on the reference library. First reported by The Hacker News from the maintainers' advisory.
| Item | Detail |
|---|---|
| Advisory | GHSA-qx49-fqc8-xw99 |
| Affected | MCP Python SDK before 1.30.0 |
| Fixed in | 1.30.0 |
| Data at risk | client_secret, authorization code, PKCE code_verifier, signed client assertion |
| Trigger | Client connects to an untrusted MCP server while holding real OAuth credentials |
What should teams do now?
Upgrade the SDK to 1.30.0. Then treat any credentials the app held while running an older version as burned: rotate the client secret, revoke outstanding refresh tokens, and re-issue any private keys used with PrivateKeyJWTOAuthProvider.
The failure mode here is the one MCP was always going to hit first: the protocol encourages applications to talk to servers users pick at runtime, and the client library trusted those servers to describe their own login setup honestly. One thing the post-mortem will say is that issuer binding belongs in the SDK, not in the integrator's checklist.
Operational takeaway: if you ship anything built on mcp.client.auth, pin 1.30.0 in your lockfile today and rotate every OAuth secret that library has ever seen.



