Skip to content

fix: prevent bearer tokens from leaking to discovery endpoints#1135

Open
Bortlesboat wants to merge 1 commit intomodelcontextprotocol:mainfrom
Bortlesboat:fix/strip-auth-from-discovery-endpoints
Open

fix: prevent bearer tokens from leaking to discovery endpoints#1135
Bortlesboat wants to merge 1 commit intomodelcontextprotocol:mainfrom
Bortlesboat:fix/strip-auth-from-discovery-endpoints

Conversation

@Bortlesboat
Copy link

Summary

Fixes #1092. When an MCP server returns 401 for an expired token, the inspector was sending the expired bearer token to OAuth discovery and metadata endpoints (/.well-known/*) during re-authentication. This caused failures in environments like Istio where sending a bad token to anonymous endpoints results in denial.

Root cause: Authorization headers were added to requestInit.headers, which the SDK's createFetchWithInit wrapper merges into all HTTP requests — including discovery/metadata fetches made by auth(), discoverOAuthProtectedResourceMetadata(), and discoverAuthorizationServerMetadata().

Fix:

  • Stop adding OAuth tokens to requestInit.headers entirely. The authProvider already handles bearer tokens dynamically via the transport's _commonHeaders() method, which only applies them to MCP server requests.
  • Exclude user-supplied custom Authorization headers from requestInit.headers. Instead, apply them through a mergeHeaders helper in the custom fetch wrapper, where the SDK's _commonHeaders() Authorization takes priority.
  • This ensures discovery/metadata endpoints never receive bearer tokens, while MCP server requests continue to receive them correctly.

Test plan

  • All 487 existing tests pass
  • TypeScript compilation clean
  • Updated 6 tests to verify Authorization headers are excluded from requestInit.headers
  • Manual testing with an OAuth-protected MCP server behind Istio to confirm discovery endpoints no longer receive bearer tokens

Stop adding Authorization headers to requestInit.headers, which the
SDK's createFetchWithInit merges into all HTTP requests including
OAuth discovery and metadata endpoints (/.well-known/*).

OAuth tokens are now handled exclusively by the authProvider via the
transport's _commonHeaders() method, which only applies them to MCP
server requests. Custom Authorization headers from the UI are applied
through the fetch wrapper's mergeHeaders helper, which lets the SDK's
_commonHeaders() take priority.

Fixes modelcontextprotocol#1092
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Sends bearer tokens to discovery endpoints

1 participant