How Do MCP SDK Flaws Expose OAuth Credentials?

The discovery of vulnerabilities in the Model Context Protocol highlights that security properties must survive state persistence, schema parsing, and routine object processing within the framework. As organizations increasingly adopt agentic AI systems that communicate across varied environments, the underlying protocols used for these interactions become critical targets for research and exploitation. The Model Context Protocol (MCP) was designed to standardize how AI agents access data and tools, but recent findings demonstrate that even robust standards can be undermined by implementation failures in client-side libraries. Specifically, the official Python and TypeScript SDKs were found to contain significant flaws in how they managed OAuth 2.0 authorization flows. These vulnerabilities did not originate from the OAuth protocol itself but rather from a failure to maintain a strict trust boundary between the MCP resource server and the authorization server. When an AI client interacts with a remote resource, it must often prove its identity or obtain permissions through an external authority. If the resource server is allowed to influence which authority the client trusts for a given set of credentials, the entire security model collapses. This creates a scenario where a malicious or compromised endpoint can essentially hijack the authentication process, leading to the unauthorized disclosure of high-value secrets such as refresh tokens and client assertions.

1. The Nature of the Credential Isolation Failure

In the early months of 2026, security researchers identified a high-severity flaw carrying a CVSS score of 7.5 within the primary SDKs used to implement the Model Context Protocol. The core of the problem was a fundamental credential isolation failure that occurred during the automated discovery of authorization endpoints. In a healthy OAuth ecosystem, a client should only present credentials to the specific authorization server that issued them. However, the MCP SDKs lacked a mechanism to verify that the server suggested by a remote resource was the same one intended to receive the client’s sensitive data. By allowing a remote MCP server to dictate the destination of authentication requests, the SDKs inadvertently created a path for credential theft. This vulnerability is particularly dangerous in agentic workflows where many connections happen in the background without direct human oversight. An attacker who controls a single MCP server could potentially harvest credentials from every client that connects to it, provided those clients were already configured to use OAuth with other legitimate services.

The technical impact of this isolation failure depends largely on the specific OAuth flow being used by the application. In unattended service-to-service interactions, the SDK might automatically send client secrets or private-key JWTs to an endpoint controlled by an adversary. In more interactive scenarios involving users, the vulnerability could expose authorization codes or PKCE verifiers during the redirection process. Because the SDKs failed to enforce a strict relationship between the credentials and the recipient, they violated the principle of least privilege at the transport layer. This type of architectural mistake is common when developers prioritize the convenience of “auto-discovery” over the rigor of explicit trust verification. In the context of MCP, where servers are often dynamic and distributed, the assumption that a resource server is an honest broker of its own authentication metadata proved to be a critical weakness that researchers were able to exploit with relatively low complexity.

2. The Mechanism of Discovery Exploitation

The exploitation of this vulnerability begins with the discovery phase defined by standards like RFC 9728. When an MCP client attempts to connect to a protected resource, it must first determine which authorization server it should use to obtain the necessary tokens. The protocol allows the resource server to provide metadata that points the client toward the correct authorization authority. Under normal circumstances, this is a useful feature that simplifies configuration for developers. However, the SDKs trusted this metadata implicitly without checking it against any pre-existing security context. A malicious MCP server can provide a response that includes an authorization_servers array containing a URL owned by the attacker. Because the SDKs were designed to follow the server’s lead, they would ingest this URL and proceed with the authentication flow, treating the attacker’s endpoint as a legitimate destination for the client’s most sensitive material.

This discovery exploitation is effective because it leverages the legitimate logic of the SDK against the user. Once the client has resolved the malicious authorization server URL, it attempts to perform standard OAuth operations, such as token exchange or client registration. If the client already possesses valid credentials for a different, legitimate authorization server, it might mistakenly include those credentials in the request to the new, untrusted endpoint. The SDK’s failure to check for an “issuer mismatch” meant that it did not realize it was handing over secrets to a third party. This highlights a broader issue in modern web standards where the flexibility of metadata-driven discovery often conflicts with the requirement for rigid credential scoping. Without a secondary check to ensure that the discovered server is actually authorized to handle the client’s current credentials, the discovery process itself becomes a delivery mechanism for malicious redirection.

3. Strategic Redirection and Attacker Control

Once an attacker has successfully manipulated the discovery metadata, they gain a high degree of control over the subsequent authentication handshake. By hosting a fake authorization server, the adversary can capture any data the MCP client sends during its attempt to authenticate. This redirection is particularly effective because it occurs at the protocol level, often bypassing traditional perimeter defenses that might only inspect traffic for known malware signatures. The attacker’s server simply acts as a “sink” for incoming POST requests containing client IDs, secrets, and refresh tokens. In some cases, the attacker can even proxy these requests back to the real authorization server after capturing the secrets, allowing the client to receive a valid token and continue its session. This “man-in-the-middle” style of attack ensures that the victim remains unaware that their credentials have been compromised until well after the event.

The level of control an attacker exerts in this scenario extends to the manipulation of the entire OAuth state. By controlling the token endpoint, the attacker can observe not just the initial secrets but also the structure of the client’s internal identity claims. For developers using private-key JWTs or signed client assertions, the attacker would receive fully formed, cryptographically signed documents that could be replayed against the legitimate issuer. The vulnerability essentially turns the client into an automated exfiltration tool that delivers secrets directly to the attacker upon request. This highlights why it is insufficient to simply secure the communication channel with TLS; the identity of the recipient must be verified independently of the instructions provided by the resource being accessed. In the absence of such verification, the MCP SDKs functioned as an open relay for sensitive authentication material, trusting the destination purely on the word of an untrusted remote server.

4. The Risk of Silent Credential Leakage

One of the most concerning aspects of the MCP SDK flaws was the potential for silent credential leakage that required no user interaction. While some OAuth flows involve a browser-based login, many MCP implementations use “unattended” flows designed for background processing and automated agents. In these cases, the client might possess a refresh token that it uses to periodically obtain new access tokens. If a malicious MCP server is introduced into the environment, the SDK might attempt to refresh the token by sending it to the attacker’s endpoint. Because this happens in the background, there is no visual indicator to a user or administrator that a sensitive secret has been sent to an unauthorized domain. This silent nature of the leakage significantly increases the window of opportunity for an attacker to use the stolen credentials before they are rotated or revoked by the legitimate system.

Furthermore, the leakage of refresh tokens is particularly damaging because these tokens often have long lifespans and are intended to provide persistent access. If an attacker captures a refresh token along with the necessary client authentication details, they can effectively impersonate the MCP client to the real authorization server. This allows for long-term unauthorized access to the data and tools that the MCP client was designed to manage. The failure of the SDKs to maintain issuer-aware storage meant that even when credentials were saved locally, they were not “pinned” to a specific authorization server. This allowed the SDK to retrieve a token meant for a secure corporate server and send it to a random URL provided by a third-party MCP integration. The scope of the risk thus expanded from a single session to the entire lifespan of the persisted credentials, affecting any application that relied on the SDK’s built-in storage mechanisms.

5. Remediating the Python SDK Environments

Remediating the vulnerability in Python environments requires a multi-step approach that begins with immediate library updates. Developers using the mcp package must transition to version 1.30.0 for the 1.x branch or 2.2.0 for the 2.x branch. These versions introduce the necessary validation logic to prevent the SDK from blindly following untrusted authorization server metadata. The update replaces the vulnerable logic with a more rigorous discovery process that enforces identity checks at every stage of the handshake. However, simply updating the dependency is often insufficient for applications that have already persisted unbound credentials or those using specific OAuth provider classes. The patch provides the tools for security, but the developer must ensure those tools are correctly applied to the application’s unique configuration and data lifecycle.

Building on the foundation of a patched library, engineering teams must reconfigure how they initialize their OAuth providers. The remediation process involves moving away from implicit trust and toward explicit configuration. In the updated Python SDK, the system is designed to handle issuer validation more aggressively, but it still requires the application to provide an “anchor of trust” when dealing with pre-registered clients. This transition is essential for preventing the re-occurrence of the discovery exploitation. By requiring the application to participate in the trust decision, the SDK ensures that the security boundary remains intact even if the remote MCP server attempts a malicious redirection. This structural change shifts the responsibility of identity verification back to the client application, where it can be managed according to the specific security policies of the organization.

6. Defining the Expected Issuer for Python

A critical step in securing Python-based MCP clients is the explicit definition of the expected issuer. When developers instantiate classes such as ClientCredentialsOAuthProvider or PrivateKeyJWTOAuthProvider, they must now pass the issuer argument. This argument serves as a hardcoded expectation of which authorization server is allowed to receive the client’s credentials. If the remote MCP server tries to advertise a different authorization server, the patched SDK will compare that discovery result against the configured issuer. If there is a mismatch, the SDK will refuse to transmit the credentials, effectively blocking the attack. This explicit binding is the primary defense against redirection, as it prevents the SDK from ever considering an attacker-controlled URL as a valid recipient for existing secrets.

In addition to configuring the issuer, developers should actively validate that the system is rejecting unauthorized metadata. The patched SDK includes logic to ensure that the issuer field within the authorization server metadata document matches the URL used to discover it. This prevents “issuer masking” attacks where a malicious server claims to be a legitimate authority while providing its own endpoints for token exchange. Furthermore, it is highly recommended to clear any stored registrations that were created before the patch was applied. Because older versions of the SDK did not bind credentials to specific issuers in local storage, these legacy records are inherently untrusted. By removing old OAuth client information and requiring the system to perform a fresh, issuer-validated registration, administrators can ensure that no “ghost” credentials remain in the system that could be exploited by a legacy vulnerability path.

7. Securing TypeScript SDK Architectures

For developers working within the TypeScript ecosystem, the remediation process mirrors the Python steps but involves specific changes to the @modelcontextprotocol/sdk and @modelcontextprotocol/client packages. The first priority is upgrading to version 1.31.0 or 2.2.0, respectively. These updates address the core issue where the TypeScript client would resolve an authorization server from discovery and then blindly apply saved client information and tokens to that server. The patched versions introduce a more robust internal state machine that tracks the issuer associated with every piece of sensitive data. This ensures that the SDK can make informed decisions about whether it is safe to reuse a stored refresh token or client secret for a newly discovered endpoint.

Beyond the initial upgrade, TypeScript implementations must adopt the expectedIssuer field in their provider configurations. This field is the TypeScript equivalent of the Python issuer argument and is essential for securing non-interactive flows. By providing an expectedIssuer, the developer tells the SDK exactly which authorization authority is trusted for the current session. The SDK then uses this value to filter discovery results and to validate that stored tokens are being sent to the correct destination. This change is particularly important for applications that use bundled providers for private-key JWTs or cross-app access, where the flow of credentials is often highly automated. Without an explicit expected issuer, even a patched SDK might default to a less secure behavior to maintain backward compatibility, leaving the application partially exposed to redirection attacks.

8. Managing Issuer-Aware Storage and Schemas

One of the unique challenges in the TypeScript remediation was ensuring that the issuer information survived the complexities of object serialization and storage. Many developers use schemas, such as those provided by the Zod library, to validate and parse data before it is written to or read from a database. If these schemas were not updated to include the new issuer field, the field would be stripped away during the parsing process, leaving the credentials “unbound” once again. To prevent this, developers must update their custom storage callbacks and data models to ensure that the issuer property is preserved alongside the tokens and client information. This creates a durable link between the secret and its intended recipient that persists across application restarts and database migrations.

The TypeScript SDK also introduced the discardIfIssuerMismatch() utility to help manage the transition from legacy, unbound state to secure, issuer-bound state. This logic allows the SDK to automatically detect when a stored token does not match the issuer currently being used for discovery. Instead of risking a credential leak, the SDK will discard the mismatched token and force a new authorization flow. This is a crucial safety mechanism for applications with long-running sessions or those that persist tokens across multiple user interactions. By clearing out the ambiguity of the past, the SDK ensures that the security of the current session is not compromised by the lack of metadata in older records. Developers should also verify that their implementations do not bypass these checks by using low-level fetch functions that might not apply the same issuer-binding logic as the higher-level providers.

9. General Audit Procedures for Engineering Teams

After applying the necessary patches and configuration changes, engineering teams must conduct a thorough audit of their MCP infrastructure to verify the effectiveness of the remediation. This audit should begin with a review of lockfiles to ensure that the deployed versions of the SDK actually match the intended secure releases. It is not uncommon for transient dependencies or cached build artifacts to cause a system to remain on a vulnerable version even after a global update has been initiated. Checking the production environment’s actual runtime manifest is the only way to confirm that the fix is in place. Additionally, teams should scan their codebase for any OAuth providers that are still being initialized without a hardcoded issuer or expected issuer, as these remain the most likely points of failure for redirection attacks.

The second phase of the audit focuses on data integrity and past exposure. If a client was previously connected to an untrusted MCP server while using a vulnerable SDK, it must be assumed that the credentials associated with that connection have been compromised. Consequently, simply patching the code is not enough; the secrets themselves must be rotated. This includes changing client secrets, rotating private keys used for JWT signing, and revoking all active refresh tokens. Organizations should also review their database records for any persisted tokens that lack an “issuer” field and update or delete them to ensure that the new SDK logic has a clean state to work with. Finally, until the entire fleet of MCP clients is fully patched and verified, it is prudent to restrict outbound connections to a whitelist of known, trusted servers to minimize the risk of encountering a malicious endpoint.

10. Actionable Next Steps and Future Protections

The investigation into MCP SDK vulnerabilities concluded with a clear set of requirements for both protocol maintainers and application developers. It was determined that the primary failure was an over-reliance on dynamic discovery without a corresponding mechanism for identity pinning. In response, the maintainers released coordinated patches that introduced issuer-aware credential handling across the Python and TypeScript ecosystems. These changes were validated against various attack scenarios, confirming that the new validation logic effectively blocked the redirection of sensitive authentication material to unauthorized third parties. The community was urged to treat these updates as mandatory, given the high potential for automated exploitation in the burgeoning market for AI agents and distributed data services.

In the final assessment, the remediation efforts focused on restoring the trust boundaries that should have existed from the protocol’s inception. Security researchers demonstrated that vulnerabilities in state persistence and schema parsing could lead to the loss of critical security context, a finding that influenced the final design of the issuer-binding logic in the SDKs. Moving forward, developers were advised to maintain a “trust-but-verify” posture when integrating with remote resource servers, ensuring that metadata is never used as the sole basis for a security decision. By implementing the explicit configuration of expected issuers and auditing legacy data stores, the industry took a significant step toward securing the infrastructure that powers the next generation of interoperable AI. The lessons learned from this incident highlighted the need for rigorous security reviews of even the most promising new frameworks before they are deployed in high-stakes production environments.

subscription-bg
Subscribe to Our Weekly News Digest

Stay up-to-date with the latest security news delivered weekly to your inbox.

Invalid Email Address
subscription-bg
Subscribe to Our Weekly News Digest

Stay up-to-date with the latest security news delivered weekly to your inbox.

Invalid Email Address