GHSA-9g45-5xwm-f3wc

ghsaUSosv

RMCP: Custom HTTP headers leak to cross-origin redirect targets

Advisory ansehen veröffentlicht 2026-09-17Lizenz: CC-BY-4.0

## Summary The `rmcp` crate's `StreamableHttpClientTransport` forwards caller-supplied custom HTTP headers (such as `X-API-Key`, `X-Auth-Token`, `Api-Key`) to cross-origin redirect targets. The `default_http_client()` function builds a `reqwest::Client` without a redirect policy override, so the default `limited(10)` policy follows `307`/`308` redirects and forwards all per-request headers except `Authorization`, `Cookie`, and `Proxy-Authorization`. Custom auth headers injected via `StreamableHttpClientTransportConfig.custom_headers` are not classified as sensitive and are therefore forwarded verbatim to any redirect target — including an attacker-controlled server. ## Affected versions - Repository: `github.com/modelcontextprotocol/rust-sdk` - Crate: `rmcp` - Commit tested: `c330fede90e4729c234f8e87fdbc5ea27a1dd10c` (HEAD, 2026-05-21) ## Vulnerability **File:** `crates/rmcp/src/transport/common/reqwest/streamable_http_client.rs` **Root cause 1 — no redirect policy override:** ```rust // Lines 302-307 fn default_http_client() -> reqwest::Client { reqwest::Client::builder() .pool_max_idle_per_host(0) .build() .expect("failed to build default reqwest client") } ``` No `.redirect(reqwest::redirect::Policy::none())` call. The default `limited(10)` policy follows up to 10 redirects and, on cross-origin redirects, strips only `Authorization`, `Cookie`, and `Proxy-Authorization`. **Root cause 2 — custom headers not sensitivity-marked:** ```rust // Lines 26-35 fn apply_custom_headers( mut builder: reqwest::RequestBuilder, custom_headers: HashMap<HeaderName, HeaderValue>, ) -> Result<reqwest::RequestBuilder, StreamableHttpError<reqwest::Error>> { for (name, value) in custom_headers { validate_custom_header(&name).map_err(StreamableHttpError::ReservedHeaderConflict)?; builder = builder.header(name, value); // no sensitivity marker } Ok(builder) } ``` Headers added via `RequestBuilder::header()` are forwarded to redirect targets because reqwest only strips headers from its own sensitive-header list (`Authorization`, `Cookie`, `Proxy-Authorization`). **Exposed API:** `StreamableHttpClientTransportConfig.custom_headers` (line 1070), intended for custom auth headers: ```rust /// Custom HTTP headers to include with every request pub custom_headers: HashMap<HeaderName, HeaderValue>, ``` ## Attack scenario 1. A caller sets `custom_headers` with an API key for the MCP server: ```rust let config = StreamableHttpClientTransportConfig::with_uri("https://mcp.example.com/mcp") .custom_headers([(HeaderName::from_static("x-api-key"), HeaderValue::from_static("my-secret-key"))].into()); ``` 2. An attacker compromises `mcp.example.com` to return `307 Temporary Redirect` to `https://attacker.example.net/capture`. 3. `rmcp` follows the redirect, forwarding `X-API-Key: my-secret-key` to `attacker.example.net`. 4. The attacker captures the secret and reuses it to call the MCP server directly. ## Negative control The `auth_header` path (`StreamableHttpClientTransportConfig::auth_header()`) sets the value via `builder.bearer_auth(auth_header)`, which maps to the `Authorization` header — stripped by reqwest on cross-origin redirects. That path is not affected. Only `custom_headers` is vulnerable. ## Fix In `default_http_client()`, disable automatic redirect following: ```rust fn default_http_client() -> reqwest::Client { reqwest::Client::builder() .pool_max_idle_per_host(0) .redirect(reqwest::redirect::Policy::none()) // <-- add this .build() .expect("failed to build default reqwest client") } ``` The transport can then inspect `3xx` responses and decide whether to follow, stripping sensitive headers before doing so. Alternatively, use `reqwest::ClientBuilder::connection_verbose` or per-request `Request::headers_mut()` to remove auth headers before the redirect is followed.

01

beschreibt (1)

Zugehörige CVEs.

IDSchweregrad ausnutzbar
CVE-2026-64684US——
RMCP is an official Rust SDK for the Model Context Protocol. Prior to 2.1.0, the rmcp crate's StreamableHttpClientTransport in crates/rmcp/src/transport/common/reqwest/streamable_h…
02

Referenzen

Externe Belege — Patches, Meldungen, Analysen.

scry

Advisories wie diese benennen die exponierten Produkte, die Angreifer auf Ihrer Angriffsfläche ins Visier nehmen. Sehen Sie mit einem kostenlosen Passiv-Scan, was exponiert ist.

Kostenloser Scan