GHSA-9g45-5xwm-f3wc

    Dashboard / Vulnerabilities / GHSA-9g45-5xwm-f3wc

    GHSA-9g45-5xwm-f3wc

    Published: 17 Sept 2026Last Modified: 17 Sept 2026

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

    Details: ## 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.

    Affected packages

    Package

    Name: rmcp

    Purl: pkg:cargo/rmcp

    Affected ranges

    Type: SEMVER

    Events:

    Introduced- 0
    Fixed -2.1.0

    Affected versions

    Common Vulnerability Scoring System

    Attack Vector
    Network
    Adjacent
    Local
    Physical
    Privileges Required
    None
    Low
    High
    User Interaction
    None
    Required
    Scope
    Unchanged
    Changed
    Confidentiality
    None
    Low
    High
    Integrity
    None
    Low
    High
    Availability
    None
    Low
    High
    GHSA-9g45-5xwm-f3wc | CVE-DB