Infrastructure & Security · Oct 3, 2026
Official MCP Python SDK flaw (CVSS 7.5) lets a malicious server steal OAuth credentials, even though the login screen is real
Adding OAuth does not protect an agent's credentials. The server it connects to must not be allowed to decide where tokens are sent
Seiichi Tanaka · Editor-in-Chief

Key points
- According to a September 28 advisory, the official MCP Python SDK's OAuth client support let the MCP server a client connected to decide where credentials were sent. The severity is CVSS 7.5
- According to Cycode researchers, users are redirected to the real Google, Okta or Azure AD page, not a phishing page, so approving the request gives no warning sign
- The hole was not in OAuth itself but in how the destination was determined. Protection requires validating the issuer and binding credentials to the authorization server that issued them
The official Python SDK for MCP contained a flaw that could hand an agent's OAuth credentials to a malicious MCP server. The SDK's maintainers published security advisory GHSA-qx49-fqc8-xw99 on September 28. Its severity is CVSS 7.5. The flaw was found by researchers at the security firm Cycode, which describes the attack in a blog post. It was covered by The Hacker News and Cybersecurity News.
The lesson is that adopting OAuth is not the same as protecting credentials. The login and the user's consent both happen on genuine screens. But if the server a client connects to can decide where tokens are sent, OAuth has not accomplished anything.
The hole: the connected server decided where credentials went
The advisory describes the problem as follows.
the SDK's OAuth client support let the MCP server a client connected to decide where the client's OAuth credentials were sent
When an agent connects to an OAuth-protected MCP server, the client first receives guidance from that server: metadata indicating which authorization server to authenticate with. From it, the client learns the URL of the login page and where to exchange an authorization code for a token. The advisory points out that the SDK used this guidance without verifying it. A malicious MCP server could point the credentials to a destination of its own.
OAuth itself was not broken. The authorization server is genuine, the user's authentication is genuine, and the tokens issued are genuine. Only one thing was swapped: where the client takes the credentials it has obtained.
The login page is real, so the attack goes unnoticed
What makes the attack troublesome is that nothing on the screen the user sees looks suspicious. Yuval Elbar, a Cycode researcher, explained on September 29:
You get redirected to the real Google/Okta/Azure AD page. It's not a phishing page... You approve it because there's nothing wrong with it.
Phishing defenses have traditionally asked users to check whether the URL is genuine and whether the page is genuine. In this attack, every one of those checks returns the right answer. The user consents to a real account on a real page, and where the credentials flow afterward never appears on screen. Human approval is no safeguard if the attack happens somewhere the approver cannot see.
For agents, the damage can be greater. An MCP client typically connects to many servers in succession. Internal tools, SaaS connectors and unfamiliar servers a developer installed to try out sit side by side in the same harness. If just one of them is malicious, consent that a user gave on a real screen for a different, legitimate service could end up in an attacker's hands. A rug-pull-style server, which behaves normally at first and rewrites its guidance later, would even slip past a vetting step at installation.
The fix: validate the issuer and bind credentials
That means the authority to decide the destination has to be taken away from the connected server. Two things are needed.
The first is issuer validation. The authorization server's metadata contains an issuer, which identifies who issued it. The client checks that this issuer matches the authorization server it expects. If they differ, the client stops rather than following the guidance.
The second is credential binding. Authorization codes, tokens and client secrets are handled as tied to the authorization server that issued them, and are not handed over when a different destination asks for them. That way, even if the connected MCP server rewrites its guidance, the destination of the credentials does not change.
Neither is a new OAuth feature. The question is whether the SDK properly performs checks already described in the standard procedure for using the metadata. That the official SDK lacked them suggests that MCP's OAuth support spread by putting getting things working first.
What users should do now
If you use the MCP Python SDK to connect to MCP servers via OAuth, the first step is to upgrade to the fixed version named in the advisory. After that, there are three points worth reviewing: whether you have ever connected to an untrusted MCP server; which authorization server's credentials were in use at the time; and, where necessary, revoking tokens and regenerating client secrets. Other SDKs and homegrown clients should also be checked for the same validation.
The flaw shows the limits of judging an agent's safety by whether it supports OAuth. The question to ask is who decides where tokens are sent. As long as the answer is the server the agent connects to, the credentials are not protected, however genuine the login screen.
Editorial cartoon
