Two MCP Python SDK OAuth providers stay exposed after upgrade until code names an issuer
MCP Python SDK maintainers fixed a flaw rated up to 7.5 that lets malicious servers steal OAuth client secrets, in versions 1.30.0 and 2.2.0. Two of the affected providers stay exposed after upgrading until the calling code passes issuer=.
The Watch · Security desk
What happened
- Cycode, which reported the flaw, used the stolen material in a test to get a valid access token from the real login service.
- The issuer checks shipped on September 7 as behavior changes, and the security advisory followed 21 days later, on September 28.
- Neither the advisory nor Cycode reports attacks using the flaw, and none has been reported elsewhere.
Why it matters
- Who's exposed exposure A service on ClientCredentialsOAuthProvider or PrivateKeyJWTOAuthProvider can be upgraded to 1.30.0 and still follow a hostile server, and its only warning is a deprecation notice Python hides by default.
- Who has to decide decision Deciding who rotates takes a record of which MCP servers each client has reached. A team without that record cannot rule out that a secret has already left.
- What it limits constraint Teams that cannot upgrade yet have to keep their clients away from every MCP server they do not trust, because older releases have no other workaround.
Next story · Security · Sep 23
Attackers are running code on BIG-IP APM boxes configured as OAuth authorization serversConfirmed6 publishers
To use the flaw, an attacker has to get a victim client to connect to a server the attacker runs [1]. That client must use the SDK over HTTP with one of four OAuth providers: OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider, or the deprecated 1.x RFC7523OAuthClientProvider [19]. It must also hold credentials for a real login service while connecting to a server it does not fully control [19]. The machine-to-machine providers need no sign-in and no person at all [10]. With the interactive provider someone has to approve a sign-in, but Cycode says the page they approve is the genuine login page, so nothing looks wrong [9]. The scores follow that split: 7.5 for the providers that run without a person present, 6.5 for the interactive one [6].
The theft happens at discovery. A client that needs to log in asks the MCP server where its authorization server can be found, and affected versions did not always check the answer [7]. A hostile server can name its own login service outright. It can also serve login details that name the user's real service while sending the credentials elsewhere [7]. Either way the PKCE proof key goes out with the authorization code [2]. That key is a one-time value meant to stop a stolen code from being reused, so handing it over removes that protection too [8]. The access token Cycode obtained in its test carried whatever permissions the app had been granted [4].
Fixed versions work out which login service they expect before fetching any details, and refuse any that name a different one [11]. For ClientCredentialsOAuthProvider and PrivateKeyJWTOAuthProvider, the advisory says "upgrading changes nothing until you also pass issuer=" [12]. Without that argument, both still follow whichever server the MCP server points them at [12]. RFC7523OAuthClientProvider has no issuer= option, so code on it has to move to one of the other two [14]. OAuth client registrations stored before the upgrade are not tied to a login service and stay that way until they are cleared once [15].
The client secret is long-lived and keeps working until it is changed [5]. The advisory lists rotation as a separate step from upgrading: rotate the secret and revoke tokens at the login service if a client may already have connected to an untrusted server [16]. SDK-built MCP servers, local stdio clients and clients that attach their own tokens are outside the flaw [20]. On that evidence, the clients that need a new secret are HTTP clients on the four affected providers that may have reached a server their owners do not fully control [25].
No CVE had been assigned as of September 29 [18]. The advisory credits eight reporters, Cycode's researcher among them [23].
What to watch
- Whether a CVE is assigned; none existed as of September 29.
- Any report of the flaw being used against a real deployment; the advisory and Cycode report none so far.
- Whether a later release makes the issuer check the default for ClientCredentialsOAuthProvider and PrivateKeyJWTOAuthProvider, or raises the warning above a hidden deprecation notice.
Clarity's read
What the record supports and how the coverage leans. The claims behind it follow.
Reality
- Evidence72
- Adoption
- Not scored
- Hype gap0
- Incentives30
- Confidence70
Claim ledger
Ranked by verification strength, evidence, and original report placement.
- [1]
A malicious MCP server could trick an application built on the official MCP Python SDK into handing over the OAuth credentials it uses to log in to a real service, according to the SDK maintainers' security advisory.
- [2]
Affected versions sent the client secret, the authorization code, and the PKCE proof key to a token endpoint the attacker controlled.
- [3]
The fix is in MCP Python SDK versions 1.30.0 and 2.2.0.
- [4]
Cycode, the security firm that reported the flaw, demonstrated in a test that the stolen credentials can be used to request a valid access token from the real login service; the resulting token carries whatever permissions the app was granted.
- [5]
The client secret is long-lived, so it keeps working until it is changed.
- [6]
The flaw is rated high (7.5) for the two providers that run without a person present, and 6.5 for the interactive provider.
- [7]
An MCP client needing to log in asks the server it connects to where its authorization server is; affected SDK versions did not always check that answer, so a malicious server could name the attacker's own server or serve login details naming the user's real service while sending the credentials elsewhere.
- [8]
The PKCE proof key is a one-time value designed to prevent a stolen authorization code from being reused, so handing it over defeats that protection.
- [9]
With the interactive provider a person still has to approve a sign-in; Cycode says the page they approve is the genuine login page, so nothing looks wrong.
- [10]
The two machine-to-machine providers need no sign-in and no person at all.
- [11]
In the fixed versions, the client works out which login service it expects before fetching any details and refuses any that name a different one.
- [12]
For ClientCredentialsOAuthProvider or PrivateKeyJWTOAuthProvider, the advisory says "upgrading changes nothing until you also pass issuer="; without it, they still follow whichever server the MCP server points them at.
- [13]
On 1.30.0, the warning about the missing issuer= is a standard deprecation warning, which Python hides by default.
- [14]
The deprecated RFC7523OAuthClientProvider has no issuer= option, so users should move to one of the other two providers.
- [15]
After upgrading, stored OAuth client registrations should be cleared once, because older ones are not tied to a login service and stay that way.
- [16]
If a client may already have connected to an untrusted server, its client secret should be rotated and its tokens revoked at the login service.
- [17]
On older versions there is no workaround other than connecting only to MCP servers you trust.
- [18]
No CVE had been assigned as of September 29.
- [19]
An application is affected if it uses the SDK as an MCP client over HTTP with OAuthClientProvider, ClientCredentialsOAuthProvider, PrivateKeyJWTOAuthProvider, or the deprecated 1.x RFC7523OAuthClientProvider, and can connect to a server it does not fully control while holding credentials for a real login service.
- [20]
MCP servers built with the SDK, local (stdio) clients, and clients that attach their own tokens are not affected.
- [21]
The issuer checks shipped in the 1.30.0 and 2.2.0 release notes on September 7, listed under behavior changes rather than as a security fix.
- [22]
The security advisory followed on September 28, the same day Cycode published its writeup.
- [23]
The advisory credits eight reporters, including Cycode's researcher.
- [24]
Neither the advisory nor Cycode reports any attacks using the flaw, and none has been reported elsewhere.
- [25]
The clients that need a rotated secret are HTTP clients on the four affected OAuth providers that may have connected to a server their owners do not fully control.
- [26]
The security advisory came 21 days after the issuer checks shipped as behavior changes.
Sources
2 independent publishers whose own reporting we read for this story.
- dev.toWhat Is the MCP Python SDK OAuth Flaw? (Sept 29, 2026)
1 article · October 1, 2026
- thehackernews.comOfficial MCP Python SDK Flaw Can Let Malicious Servers Steal OAuth Credentials
2 articles · September 29, 2026
Topics and entities
Topics
- OAuth 2.0 Security
- AI agent tooling security