October 23, 2026
Upgrading Your MCP SDK Won’t Close the OAuth Hole on Its Own
I reproduced the October 2026 MCP SDK credential leak in a local lab. The patch helps, but only if you also change one line of config.

By Waseem Anjum
1 min read
In October 2026, both official MCP SDKs, TypeScript and Python, published high-severity advisories for the same flaw within two days of each other. A malicious or compromised MCP server could name its own authorization server, and your client would send it your OAuth credentials: a refresh token, a client secret or a signed assertion. In TypeScript it's CVE-2026–104850. Python's version is GHSA-qx49-fqc8-xw99.
The advice everyone repeated was "upgrade." TypeScript SDK 1.31.0 and client 2.2.0 carry the fix, and so do Python mcp 1.30.0 and 2.2.0. I wanted to see whether that was enough, so I built a small lab with a fake MCP server pointing at an attacker-controlled authorization server and tested four client setups.
On 1.30.1, all four leaked. On 1.31.0 and 1.32.1, the leak stopped only when the client knew which issuer to expect. A ClientCredentialsProvider created without expectedIssuer still sent the client secret to the attacker. Credentials stored before the upgrade, which have no issuer field, still leaked too.
So the real fix has three parts. Upgrade the SDK. Pass expectedIssuer everywhere you build a provider. Then clear tokens saved before the fix and rotate any secret that might have gone out.
The server side matters just as much, because the MCP authorization spec is already sound. It requires resource indicators, audience validation, PKCE and issuer checks. Most incidents come from implementations that skip them. On the MCP server behind my own site, a few rules do most of the work:
- Every access token must be issued for the server's own resource URI. Tokens meant for anything else are rejected, and tokens are never passed through to another API.
- Every tool has a scope, and a tool with no scope mapped to it is denied by default.
- tools/list is filtered by scope, so an agent can't call what it can't see. A read-only token sees 4 of 22 tools, and 680 tokens of tool definitions instead of 7,778.
- Every message in a JSON-RPC batch is checked, not just the first one.
- Every write is logged with the actor, the tool and the diff, and can be undone. Only hashes of tokens and IPs are stored.
Prompt injection is the other half of the story. One compromised agent can pass instructions to another over MCP, so treat tool output as untrusted input and require approval for anything destructive.
The full write-up, with the lab setup, the fixed configs, the authorization flow and a security checklist, is on my site:
MCP Security in 2026: OAuth CVEs Tested and Best Practices | Waseem Anjum MCP security in 2026: the OAuth SDK flaws (CVE-2026-104850) reproduced, why upgrading isn't enough, and how to secure…