Attack ChainAIDerived
Hypothetical attack flow derived from CVE metadata – not a confirmed exploit chain
-
AccessOperate malicious or compromised MCP server
-
DeliveryVictim client connects holding stored OAuth credentials
-
ExploitServer advertises attacker-controlled authorization server
-
ExecutionSDK sends refresh_token and client_secret
-
ImpactAttacker captures and replays stolen credentials
Vulnerability Assessment
| Weakness |
CWE
OWASP Top 10:2025
A08:2025 - Software or Data Integrity Failures
ASVS 5.0
V15 - Secure Coding and Architecture Data authenticity verification
|
| Exploitation Conditions | Exploitation requires ALL of: (1) the application uses the SDK's OAuth client over HTTP via an authProvider on a transport, the withOAuth() middleware, or direct auth()/fetchToken() calls; (2) it holds credentials for a legitimate authorization server (a stored refresh_token/client_secret, or a bundled provider's client_secret/signed assertion); and (3) it connects to an MCP server the operator does not fully trust. For @modelcontextprotocol/client 2.x the window is narrower - only bundled providers (ClientCredentialsProvider, PrivateKeyJwtProvider, StaticPrivateKeyJwtProvider, CrossAppAccessProvider) constructed WITHOUT expectedIssuer, credentials stored/supplied WITHOUT issuer, direct fetchToken() calls, or custom providers reading storage back through OAuthTokensSchema/OAuthClientInformationSchema. Limiting factors that reduce real-world exposure: stdio clients are NOT affected, MCP servers built with the SDK are NOT affected, and the trigger depends on the victim choosing to connect to an untrusted server rather than a purely attacker-initiated reach. Note residual risk even after upgrade: a fresh interactive sign-in, and credentials persisted without an issuer before upgrading, still go to whichever authorization server the MCP server names until issuer is added or the credentials are cleared; skipIssuerMetadataValidation:true on 2.x also defeats the fix. |
| Impact | This is a credential-disclosure flaw (CWE-345, Insufficient Verification of Data Authenticity) in the MCP TypeScript SDK's OAuth client, rated CVSS 7.5 with vector AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N - pure confidentiality impact, no integrity or availability loss, which directly contradicts the single input Tag 'Denial Of Service'. No EPSS score was provided, so exploitation-probability cannot be quantified from this data. The CVE is NOT in CISA KEV and no public exploit code is referenced, so this is no public exploit identified at time of analysis - not active exploitation. The network vector and lack of required interaction make the mechanism trivial once triggered, but real-world risk is gated by a meaningful precondition the CVSS vector understates: the victim client must already hold valid OAuth credentials AND voluntarily connect to an MCP server the operator does not fully trust. This is therefore a genuine priority for the specific population of applications using the SDK's HTTP OAuth client against semi-trusted servers (where leaked refresh_tokens, client_secrets, or signed assertions enable downstream impersonation against the legitimate authorization server), but closer to a moderate, conditional risk than a mass-exploitable internet-facing bug for the general population. Key missing signals: no EPSS, no KEV confirmation, no POC evidence - absence noted explicitly, not treated as safety. |
| Exploit ScenarioDerived | An attacker stands up (or compromises) an MCP server and lures a victim application - one using the SDK's OAuth client over HTTP while holding credentials for a legitimate authorization server - into connecting to it. With no user interaction, the attacker's server advertises its own authorization server and the SDK sends the stored refresh_token and client_secret (or a bundled provider's client_secret/signed assertion) to the attacker-controlled endpoint, which the attacker then replays against the real authorization server. No public exploit code is referenced, but the network vector and low attack complexity make the credential-theft step straightforward once a connection is established. |
Get an e-mail when this CVE is exploited, patched or re-scored. Free account.
Alert meAnalysisAIv1 – Oct 06, 2026
Credential disclosure in the MCP TypeScript SDK OAuth client (npm @modelcontextprotocol/sdk 1.12.0 through 1.30.1, and @modelcontextprotocol/client 2.0.0 through 2.1.0 in narrower configurations) lets a malicious or compromised MCP server direct the client's stored OAuth credentials to an authorization server of the attacker's choosing. Because saved credentials were never bound to the authorization server that issued them, a remote, unauthenticated attacker who controls or compromises the MCP server the victim connects to can silently receive a stored refresh_token and client_secret - or a bundled provider's client_secret or signed assertion - yielding full confidentiality impact (CVSS 3.1 7.5, AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N, per the PR:N vector the request is unauthenticated). No public exploit code and no confirmed active exploitation were identified at time of analysis; exploitation requires the victim application to use the SDK's OAuth client over HTTP and to connect to an MCP server it does not fully trust while holding credentials for a legitimate authorization server.
RemediationAI
Vendor-released patch: upgrade to @modelcontextprotocol/sdk 1.31.0 or later for the 1.x line, or @modelcontextprotocol/client 2.2.0 and @modelcontextprotocol/core 2.2.0 or later for the 2.x line, per the fix references https://github.com/modelcontextprotocol/typescript-sdk/pull/2887 and commit edd12e282620ebf770d67316f19cf91d4112a1bd. Upgrading alone is insufficient in three cases: bundled providers (ClientCredentialsProvider, PrivateKeyJwtProvider, StaticPrivateKeyJwtProvider, CrossAppAccessProvider) must be constructed with expectedIssuer set to the authorization server's issuer (e.g. expectedIssuer: 'https://auth.example.com'), otherwise they still follow whichever authorization server the MCP server names; any credentials persisted without an issuer - including everything 1.x saved before 1.31.0 - must have the issuer added or be cleared so users re-authenticate, since those credentials otherwise still travel to the first authorization server named; and custom OAuthClientProvider implementations must persist exactly what saveTokens()/saveClientInformation() receive, including issuer, and return issuer in clientInformation() for pre-registered credentials. If an affected client may have connected to an untrusted MCP server, rotate its client secret or signing key and revoke its tokens. Residual gaps not covered by the fix: a fresh interactive sign-in still goes to the authorization server named by the MCP server (only complete sign-ins for trusted servers, which is a trade-off against usability), direct calls to refreshAuthorization()/exchangeAuthorization() remain unguarded, and 2.x with skipIssuerMetadataValidation: true defeats issuer validation and should be disabled. If upgrading is not immediately possible, restrict OAuth clients to MCP servers you trust; note that 2.0.0 and 2.1.0 already accept expectedIssuer, so that pinning can be applied as an interim compensating control at the cost of manual configuration.
Affected VersionsENISA
Affected Packages
Source: OSV (Open Source Vulnerabilities)
Affects your stack
Affects 4 packages in npm, euvd
Checking this CVE against your own stacks and servers is part of the Basic plan and up.
Technical ContextAI · show details
The Model Context Protocol (MCP) TypeScript SDK implements an OAuth 2.x client used by HTTP-based MCP transports, the withOAuth() middleware, and direct auth()/fetchToken() calls; the client discovers the authorization server's metadata from the MCP server it is connecting to. The root cause is CWE-345, Insufficient Verification of Data Authenticity: the OAuth client accepted the authorization server identity selected by the peer (the MCP server) instead of pinning credentials to the issuer they were registered with, so cached tokens and client information were transmitted to whatever authorization-server URL the MCP server advertised. The fix introduces an issuer stamp on saved credentials and an expectedIssuer constructor option on bundled providers (ClientCredentialsProvider, PrivateKeyJwtProvider, StaticPrivateKeyJwtProvider, CrossAppAccessProvider); fetchToken() now throws AuthorizationServerMismatchError before transmitting anything when client information is bound to a different authorization server, OAuthTokensSchema and OAuthClientInformationSchema accept and preserve the optional issuer field, and constructing the bundled providers without expectedIssuer is deprecated with a console.warn. Note that the supplied tag set labels this 'Denial Of Service', which contradicts both the CWE-345 classification and the CVSS vector (C:H/I:N/A:N, confidentiality-only) - the authoritative assessment is pure credential disclosure, not availability loss. MCP servers built with the SDK and stdio clients are explicitly not affected, and CPE entries pkg:npm/@modelcontextprotocol_sdk and pkg:npm/@modelcontextprotocol_client confirm the two npm packages tracked.
Know when the next one hits your stack
- Watch products and get an email when something new is published
- Check this CVE against your own stack and servers
- Exploit and PoC references, threat intelligence from 22 sources
No credit card · 7-day full trial
Severity by source
AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:N
Credential disclosure over HTTP with no interaction once a client connects, so C:H and AV:N/AC:L/PR:N/UI:N; no direct integrity or availability impact, so I:N/A:N.
Primary rating from Vendor (https://github.com/modelcontextprotocol/typescript-sdk).
CVSS VectorVendor: https://github.com/modelcontextprotocol/typescript-sdk
DescriptionCVE.org
Summary
In affected versions, the SDK's OAuth client let the MCP server decide which authorization server received the client's OAuth credentials. Credentials were not tied to the authorization server they belong to.
A malicious or compromised MCP server could name its own authorization server. With no user interaction, the client would send it:
- the
refresh_tokenandclient_secretstored from an earlier sign-in - the
client_secretor signed assertion configured on a bundled provider
Am I affected?
Yes, if both of these hold:
- your application uses the SDK's OAuth client over HTTP, through any of:
- an
authProvideron a transport - the
withOAuth()middleware - direct calls to
auth()orfetchToken() - it may connect to an MCP server you do not fully trust while holding credentials for a legitimate authorization server
Affected versions:
@modelcontextprotocol/sdk1.12.0 through 1.30.1@modelcontextprotocol/client2.0.0 through 2.1.0, only for:- bundled providers without
expectedIssuer - credentials stored or supplied without
issuer - direct calls to
fetchToken() - providers that read storage back through
OAuthTokensSchemaorOAuthClientInformationSchema
Not affected:
- MCP servers built with the SDK
- stdio clients
Fix
Upgrade to:
- 1.x:
@modelcontextprotocol/sdk1.31.0 or later - 2.x:
@modelcontextprotocol/client2.2.0 or later, and@modelcontextprotocol/core2.2.0 or later if you import it directly
The client now records the authorization server as issuer on saved credentials and does not send them to a different one. The user signs in again, or the call throws.
In the following cases, upgrading to the patched version is not enough. You also need to make a change:
- Bundled providers (
ClientCredentialsProvider,PrivateKeyJwtProvider,StaticPrivateKeyJwtProvider,CrossAppAccessProvider): passexpectedIssuer, for exampleexpectedIssuer: 'https://auth.example.com'. Without it they still use whichever authorization server the MCP server names. - Credentials saved without
issuer: tokens and client information yourOAuthClientProviderpersisted (file, keychain, database) before upgrading, including everything 1.x saved before 1.31.0. They still go to whichever authorization server is named at first use. Addissuerto them, or clear them so users sign in again. - Your own
OAuthClientProvider: save exactly whatsaveTokens()andsaveClientInformation()are given, includingissuer. For pre-registered credentials, includeissuerin whatclientInformation()returns.
Not covered by this fix:
- a new interactive sign-in, which still goes to the authorization server the MCP server names. Only complete sign-ins for servers you trust.
refreshAuthorization()andexchangeAuthorization()called directly- 2.x with
skipIssuerMetadataValidation: true
If an affected client may have connected to an untrusted MCP server, rotate its client secret or signing key and revoke its tokens.
If you cannot upgrade yet, connect OAuth clients only to MCP servers you trust. 2.0.0 and 2.1.0 already accept expectedIssuer.
Technical POC Analysis
No runnable PoC is present in the supplied evidence.
Full technical POC analysis - root cause, step-by-step exploitation and patch breakdown - is part of the Pro and Business plans.
Executive ViewAI
A high-severity credential disclosure flaw in the widely used MCP TypeScript SDK (@modelcontextprotocol/sdk versions 1.12.0 through 1.30.1, plus @modelcontextprotocol/client 2.0.0 through 2.1.0) allows an attacker who controls or compromises an MCP server to silently harvest the OAuth refresh tokens and client secrets that any connecting application has stored. Because the leak occurs without user interaction and without authentication, any team shipping or operating MCP-enabled clients - including internal AI tooling and customer-facing integrations - could expose long-lived third-party credentials. Leadership should care because stolen refresh tokens and provider client secrets permit persistent, hard-to-detect access to downstream SaaS and identity providers, turning a single SDK dependency into an enterprise-wide trust and compliance exposure.
Apply vendor patch.
Threat Intelligence Overview
How this decision was reached
The engine reads each signal below and applies a fixed list of rules from top to bottom. The first rule that matches sets the recommended action – like a statement, every line is shown.
EUVD-2026-93491
GHSA-6qxp-vccf-f47h
NVD
CVE.org
EPSS
Vulnrichment
Exploit-DB