You assume an MCP server will only supply valid OAuth metadata and never steer your client’s token exchange elsewhere. That assumption is wrong. A flaw in the official MCP Python SDK let attackers poison the token_endpoint in server-supplied OAuth metadata, causing the client to send its client secret, authorisation code, and PKCE code verifier to a fake endpoint. The attacker then completes the OAuth flow with the real provider and obtains a valid access token. This is not a protocol flaw—it was a practical bug in a widely used client library. The same pattern enables broader threats: excessive OAuth scopes turn stolen tokens into master keys, plaintext connections leak tokens to network attackers, and cached metadata can persist malicious endpoints across sessions.
The redirect that should never happen
The Model Context Protocol (MCP) lets AI clients connect to external data sources and tools via servers. When a server requires OAuth, the client handles the flow: it redirects the user to the authorisation server, receives an authorisation code, and then exchanges that code for an access token at the token_endpoint. The client obtains the token_endpoint URL—and other metadata—from the MCP server, which acts as the OAuth client’s source of truth for discovery.
The vulnerability existed in the SDK’s OAuth client providers, including OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider, and the deprecated RFC7523OAuthClientProvider. When initiating the token exchange, the client would accept the token_endpoint supplied by the MCP server without validating it against a known issuer or trusted registry. A malicious server could respond with a token_endpoint pointing to an attacker-controlled server.
The vulnerable SDK would then send the OAuth client secret, the authorisation code, and the PKCE code verifier to this fake endpoint. With these components, the attacker could complete the OAuth flow with the real authorization provider and obtain a valid access token. That token carries all the permissions your application was granted. This attack works over HTTP connections to untrusted servers, making development setups and poorly configured deployments prime targets.
This is a classic case of failing to validate server-supplied data. The client delegated a critical security decision—where to send credentials—to the very entity it was trying to authenticate against. The Cloud Security Alliance’s best practices for agentic MCP explicitly warn against trusting server-provided metadata without cryptographic verification.
Your exposure is broader than one SDK
While the specific Python SDK flaw is patched, the pattern of attack is endemic to the agentic ecosystem. The same research that disclosed this flaw catalogues related threats that stem from trusting MCP servers implicitly. Each one breaks a different part of the trust model you likely assume.
Picture a scenario where an attacker uploads a useful, benign MCP server to a public registry. After it gains adoption, they push a silent update that changes the OAuth metadata it supplies—introducing a malicious token_endpoint. Existing clients that cached the metadata or failed to revalidate it on reconnect would now send credentials to the attacker’s endpoint on every future exchange.
In another case, a vulnerability in the mcp-remote package allowed a server to execute arbitrary commands on a victim's machine by passing a malicious URL directly to the system's open function. This pre-authentication remote code execution flaw, patched in version 0.1.16, gave attackers a direct path to harvest session tokens from memory.
Furthermore, attackers can register servers with names similar to popular services, exploiting name-based discovery in AI assistants—a server spoofing attack. Or they can compromise a legitimate package in the supply chain, as happened with a backdoored postmark-mcp server that secretly BCC'd emails to an attacker. These are not isolated issues. They represent a systemic risk: the MCP server you connect to is a powerful, privileged extension of your AI agent. Its security is your security.
Principle: treat servers as untrusted code
The foundational defence is a shift in mindset. You must treat every MCP server, especially those from outside your organisation, as untrusted code executing within your security perimeter. This is not merely about network isolation; it is about applying the principle of least privilege to every component the server interacts with. The OAuth flaw occurred because the client had excessive trust in the server's instructions about identity—a core security function.
This principle extends to how you manage identity itself. An MCP server should never receive credentials or tokens with more scope than its specific function requires. The practice of granting broad *.read or *.write OAuth scopes because it is convenient creates a massive attack surface. If a token is stolen via a flaw like this, the attacker inherits those sweeping permissions.
You must move towards capability-based scoping, where each token is minted for a specific, limited action. Managing these non-human identities is a discipline in itself, requiring clear ownership and lifecycle controls. Your MCP server security configuration is code. It defines trust relationships, network access, and identity boundaries.
As with any critical code, it must be version-controlled, reviewed, and deployed through a pipeline that includes security validation. You would not let a random npm package configure your firewall rules; do not let an untrusted MCP server configure your OAuth endpoints.
Immediate actions to close the credential leak
For the specific SDK vulnerability, the path is clear. First, immediately upgrade any application using the MCP Python SDK to version 1.30.0 or 2.2.0, which contain the fix. If you are using a ClientCredentialsOAuthProvider or PrivateKeyJWTOAuthProvider, you must explicitly pass the issuer= parameter in your code. This pins the expected OAuth identity and prevents the server from redirecting the token exchange.
Second, you must rotate every OAuth client secret that was used with a vulnerable SDK version while connected to an HTTP-based or untrusted MCP server. Assume those secrets are compromised. Revoke all existing access tokens and refresh tokens associated with those client credentials.
Third, clear any stored OAuth client registrations from your system after the upgrade. Cached metadata might still point to malicious endpoints. Fourth, enforce TLS for all MCP connections, without exception. This vulnerability, and others like session hijacking, are trivial to exploit over plain HTTP.
A network-level attacker can intercept and modify server responses just as easily as a malicious server can. TLS provides a baseline of confidentiality and integrity that is mandatory.
Building a resilient MCP architecture
Patching one library is reactive. Building a resilient architecture is proactive. Start by implementing a gateway or broker for all MCP connections. This central component can enforce policies: which servers are allowed, whether connections use TLS, and what OAuth scopes are permitted. It can validate server metadata against an allow-list before it reaches your client.
This pattern moves trust decisions out of the individual client SDK and into a controlled, auditable service. Adopt cryptographic signing for tool definitions. Frameworks like the Enhanced Tool Definition Interface allow servers to sign their tool manifests. Your client can verify these signatures against a trusted public key, ensuring the tools have not been tampered with after approval—preventing the rug-pull attack.
Combine this with version pinning; your client configuration should specify the exact version of an MCP server it expects to communicate with. Isolate and monitor. Run external MCP servers in sandboxed environments with minimal network access. Use tools like mcp-scan to analyse server behaviour and tool descriptions for anomalies.
Monitor for changes in tool definitions between sessions, as this can indicate a compromised server. For multi-tenant deployments, enforce strict tenant isolation at the data layer to prevent cross-tenant information leakage, a risk highlighted in past incidents.
Questions people ask
How does an MCP server poison the OAuth metadata?
An MCP server supplies OAuth discovery metadata—including the token_endpoint, authorization_endpoint, and issuer—when the client first connects. A malicious server can return a token_endpoint pointing to an attacker-controlled server. If the client does not validate this endpoint against the expected issuer, it will send the client secret, authorisation code, and PKCE code verifier to the fake endpoint, enabling full token theft.
What scopes should I request for MCP servers?
Request only the scopes required for the specific capability the server provides. For example, if a server only needs to read a user’s calendar, request calendar.read instead of calendar.readwrite or *.read. Avoid wildcard scopes like *.read unless absolutely necessary. Over-broad scopes turn stolen tokens into master keys, multiplying the damage from credential leaks.
How do I keep tokens out of logs?
Never log raw access or refresh tokens. Use masking or redaction in logging libraries before any token leaves the application. Configure your MCP client to strip tokens from HTTP request/response bodies before logging. Store tokens in memory or secure, encrypted storage—never in plaintext files or configuration. The Cloud Security Alliance recommends treating tokens as secrets and applying the same controls you use for API keys and passwords.
Why does TLS matter for MCP even if the server is trusted?
TLS protects the confidentiality and integrity of the OAuth handshake. Without TLS, a network attacker can intercept and modify server responses—including the OAuth metadata—just as easily as a malicious server can. Even a trusted server can be compromised or impersonated via DNS hijacking, BGP hijacking, or compromised CDNs. TLS ensures that the metadata you receive has not been tampered with in transit.
Close
The MCP OAuth flaw is a stark lesson in inherited trust. Your AI agent's security is only as strong as the weakest link in its extended toolchain—a chain that now includes dynamically connected, third-party servers. Defending requires a layered approach: immediately applying patches, rigorously rotating credentials, and then architecting for resilience.
You must gatekeep server connections, cryptographically verify tool integrity, scope permissions with surgical precision, and enforce TLS everywhere. The era of AI agents demands a new security model, one where non-human identities are managed as carefully as human ones, and where every component, as we've argued before, is treated as a new kind of insider. Do not let the convenience of connectivity become the vector of your compromise.
Sources
- Cloud Security Alliance, Agentic MCP Security Best Practices (opens in a new tab)
- CSA Research Note, Indirect Prompt Injection in the Wild (opens in a new tab)