MCP HTTP client: cross-origin redirect handling strips credentials from the caller's headers, so a retry to the original server goes out without Mcp-Session-Id and Cookie
- Dominant language
- TypeScript
- Stars
- 193k
- Forks
- 42.4k
- PR merge metrics
- PR metrics pending
Description
Does this issue occur when all extensions are disabled?: Yes
- VS Code Version: main (f44f55cde0c), also present in current Insiders
- OS Version: Linux x64 (Pop!_OS 22.04)
Since #320347, `McpHTTPHandle._fetch` removes `Authorization`, `Cookie`, `Proxy-Authorization` and `Mcp-Session-Id` when a redirect crosses origins. It does so with `delete init.headers[name]` on the `init` object it received, and that object belongs to the caller: `_sendStreamableHttp`, `_attachStreamableBackchannel` and `_attachSSE` pass the same `headers` object both as `init.headers` and as the `headers` argument of `_fetchWithAuthRetry`, whose retry is `() => this._fetch(mcpUrl, init)`.
After one cross-origin hop, a retry against the configured server (for example after a 401 from the redirect target) is therefore sent to the original origin without `Mcp-Session-Id` and `Cookie`. `Authorization` is put back by `_addAuthHeader`; the other two are not. For a streamable-HTTP server the retry arrives without the session id, which the server may reject as an unknown session.
Steps to Reproduce (unit level):
1. Call `_fetch` with `headers = { 'Mcp-Session-Id': 's', Cookie: 'a=b', Authorization: 'Bearer t' }` against a server that answers 307 to another origin.
2. After the call returns, inspect the `headers` object that was passed in: `Mcp-Session-Id`, `Cookie` and `Authorization` are gone.
3. Call `_fetch` again with the same `init` against the original origin: the request goes out without them.
Expected: the stripping applies to the redirected request only, as `fetch` does in browsers, and the caller's headers are left intact.
Contributor guide
Assessment
This issue has not been assessed yet.