[Vulnerability] modelcontextprotocol/python-sdk: OAuth Issuer Validation Bypass / Man-in-the-Middle Attack #8
Description
Potential Security Vulnerability Detected
Repository: modelcontextprotocol/python-sdk
Commit: d060b36
Author: Max
Date: 2026-09-02T15:51:22Z
Commit Message
Validate the authorization server metadata issuer on every discovery path (#3398)
Pull Request
PR: #3398 - Validate the authorization server metadata issuer on every discovery path
Labels: None
Description:
The OAuth client now decides which issuer it expects before it fetches any authorization server metadata, and checks what follows against that one value: the metadata's issuer (RFC 8414 section 3.3) on the legacy no-PRM path as well as the PRM path, the SEP-2352 binding of stored credentials, and the issuer recorded on a new registration. A 403 scope step-up goes through the same discovery when it holds no metadata yet, and the two machine-to-machine providers gain an optional issuer= so pre...
Analysis
Vulnerability Type: OAuth Issuer Validation Bypass / Man-in-the-Middle Attack
Severity: High
Description
The OAuth client was not validating the authorization server metadata's issuer field on the legacy discovery path (when no Protected Resource Metadata is available). An attacker could perform a man-in-the-middle attack by serving malicious authorization server metadata from a different issuer, allowing credential binding to be re-evaluated against an attacker-controlled issuer and potentially intercepting tokens or performing authentication bypass. The patch enforces RFC 8414 section 3.3 compliance by validating the issuer matches the expected value on all discovery paths.
Affected Code
// Before patch: issuer was not validated on legacy path
1. **Discovery.** It reads the `WWW-Authenticate` header, fetches the server's Protected Resource Metadata from `/.well-known/oauth-protected-resource`, learns which authorization server protects this resource, and fetches *that* server's metadata.
Proof of Concept
1. Client requests MCP server resource, gets 401 Unauthorized
2. MCP server has no Protected Resource Metadata (legacy path)
3. Client fetches authorization server metadata from the MCP server's origin: http://mcp-server.example.com/.well-known/oauth-authorization-server
4. Attacker intercepts and returns: {"issuer": "http://attacker.com", "token_endpoint": "http://attacker.com/token", ...}
5. Before patch: Client accepts this metadata without checking if issuer matches the expected value
6. Client's credential binding gets re-evaluated against attacker's issuer, tokens sent to attacker
7. After patch: Client validates issuer field and rejects metadata where issuer != MCP server's origin, preventing the attack
This issue was automatically created by Vulnerability Spoiler Alert.
Detected at: 2026-10-06T07:14:23.409Z
Activity