Skip to content

Security2 publishers3 min readPublished Updated

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

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

Photograph accompanying Two MCP Python SDK OAuth providers stay exposed after upgrade until code names an issuer
Photo: thehackernews.com

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.

Compiled by The WatchSomething wrong?How this is made

Why it matters

  • 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.
  • 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.
  • 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.

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 [13]. It must also hold credentials for a real login service while connecting to a server it does not fully control [13]. The machine-to-machine providers need no sign-in and no person at all [12]. 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 [11]. The scores follow that split: 7.5 for the providers that run without a person present, 6.5 for the interactive one [7].

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 [9]. 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 [9]. 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 [10]. The access token Cycode obtained in its test carried whatever permissions the app had been granted [5].

Fixed versions work out which login service they expect before fetching any details, and refuse any that name a different one [15]. For ClientCredentialsOAuthProvider and PrivateKeyJWTOAuthProvider, the advisory says "upgrading changes nothing until you also pass issuer=" [16]. Without that argument, both still follow whichever server the MCP server points them at [16]. RFC7523OAuthClientProvider has no issuer= option, so code on it has to move to one of the other two [18]. OAuth client registrations stored before the upgrade are not tied to a login service and stay that way until they are cleared once [19].

The client secret is long-lived and keeps working until it is changed [6]. 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 [20]. SDK-built MCP servers, local stdio clients and clients that attach their own tokens are outside the flaw [14]. 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 [2].

No CVE had been assigned as of September 29 [8]. The advisory credits eight reporters, Cycode's researcher among them [24].

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.
Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories