fix: prevent duplicate Authorization header in SSE client#1919
Open
Christian-Sidak wants to merge 2 commits intomodelcontextprotocol:mainfrom
Open
fix: prevent duplicate Authorization header in SSE client#1919Christian-Sidak wants to merge 2 commits intomodelcontextprotocol:mainfrom
Christian-Sidak wants to merge 2 commits intomodelcontextprotocol:mainfrom
Conversation
When both requestInit.headers and eventSourceInit.fetch provided the same Authorization header, the SDK's internal fetch wrapper passed a Headers instance (lowercase keys) to the user's custom fetch, which then merged it with its own closure headers (original case). The resulting plain object had both "authorization" and "Authorization" keys, producing "Bearer X, Bearer X" after Headers normalization. Fix: remove eventSourceInit.fetch from the fetchImpl resolution chain in _startOrAuth(). The SDK's wrapper already fully controls the fetch call to EventSource, so fetchImpl should be the raw transport (opts.fetch or global fetch), not the user's header-injecting wrapper. Closes modelcontextprotocol#1872
🦋 Changeset detectedLatest commit: db4d179 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
@modelcontextprotocol/client
@modelcontextprotocol/server
@modelcontextprotocol/express
@modelcontextprotocol/fastify
@modelcontextprotocol/hono
@modelcontextprotocol/node
commit: |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #1872. When both
requestInit.headersandeventSourceInit.fetchprovide the sameAuthorizationheader, the server receives a duplicated value (Bearer X, Bearer X) due to a case mismatch between theHeadersinstance (lowercaseauthorization) and the user's closure headers (original caseAuthorization).eventSourceInit.fetchfrom thefetchImplresolution chain in_startOrAuth()-- the SDK's internal wrapper already fully controls the fetch call passed to EventSource, sofetchImplshould use the raw transport (opts.fetchor globalfetch), not the user's header-injecting wrappereventSourceInit.fetchbeing used asfetchImplAuthorizationheader when bothrequestInit.headersandeventSourceInit.fetchinject the same tokenRoot cause
_commonHeaders()returns aHeadersinstance which lowercases keys (authorization)_startOrAuth()usedeventSourceInit.fetchasfetchImpl, calling it with theHeadersinstanceHeadersinto a plain object (lowercase keys), then merges closure headers (original case), producing bothauthorizationandAuthorizationas separate keysnew Headers({ authorization: X, Authorization: X })joins them per HTTP spec intoX, XTest plan
requestInit.headersandeventSourceInit.fetchboth setAuthorization, server receives exactly one valueeventSourceInit.fetchis no longer called asfetchImpl(spy test)