GHSA-9g45-5xwm-f3wc: Infoleak

Published Sep 17, 2026
·
Updated

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 defaulthttpclient() 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.customheaders 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/streamablehttpclient.rs

Root cause 1 — no redirect policy override:

rust // Lines 302-307 fn defaulthttpclient() -> reqwest::Client { reqwest::Client::builder() .poolmaxidleperhost(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 applycustomheaders( mut builder: reqwest::RequestBuilder, customheaders: HashMap<HeaderName, HeaderValue>, ) -> Result<reqwest::RequestBuilder, StreamableHttpError<reqwest::Error>> { for (name, value) in customheaders { validatecustomheader(&name).maperr(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.customheaders (line 1070), intended for custom auth headers:

rust /// Custom HTTP headers to include with every request pub customheaders: HashMap<HeaderName, HeaderValue>,

Attack scenario

1. A caller sets customheaders with an API key for the MCP server: rust let config = StreamableHttpClientTransportConfig::withuri("https://mcp.example.com/mcp") .customheaders([(HeaderName::fromstatic("x-api-key"), HeaderValue::fromstatic("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 authheader path (StreamableHttpClientTransportConfig::authheader()) sets the value via builder.bearerauth(authheader), which maps to the Authorization header — stripped by reqwest on cross-origin redirects. That path is not affected. Only customheaders is vulnerable.

Fix

In defaulthttpclient(), disable automatic redirect following:

rust fn defaulthttpclient() -> reqwest::Client { reqwest::Client::builder() .poolmaxidleperhost(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::connectionverbose or per-request Request::headersmut() to remove auth headers before the redirect is followed.

Affected Software

1 affected componentFixes available
rust/rmcp<2.1.0
2.1.0

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Upgrade

    Upgrade rust/rmcp to a version that resolves this vulnerability.

    Fixed in 2.1.0
  2. Configuration

    In default_http_client(), disable automatic redirect following by adding `.redirect(reqwest::redirect::Policy::none())` to the reqwest::Client/RequestBuilder so that `307/308` redirects are not followed (prevents forwarding `StreamableHttpClientTransportConfig.custom_headers` like `X-API-Key` to attacker-controlled redirect targets).

    rmcp::StreamableHttpClientTransport (default_http_client) reqwest redirect policy (redirect(reqwest::redirect::Policy::none())) = Policy::none()
  3. Configuration

    Ensure values provided via `StreamableHttpClientTransportConfig.custom_headers` (e.g., `x-api-key`) are sensitivity-marked/classified as sensitive so they are not forwarded to redirect targets on cross-origin redirects. (The issue is that custom headers are not classified as sensitive and are therefore forwarded verbatim.)

    rmcp::StreamableHttpClientTransportConfig.custom_headers custom_headers sensitivity marking (sensitive-header classification) = mark auth-like custom headers as sensitive so reqwest strips them on cross-origin redirect

Event History

Sep 17, 2026
Advisory Published
via GitHub·02:48 PM
Data Sourced
via GitHub·02:48 PM
DescriptionSeverityWeaknessAffected Software

Frequently Asked Questions

1

Who is exposed to credential leakage?

Deployments using rmcp's StreamableHttpClientTransport with custom headers such as X-API-Key, X-Auth-Token, or Api-Key are exposed when the client follows a cross-origin redirect. Clients that do not send sensitive values in custom headers are not described as affected by this issue.

2

What must an attacker be able to do to exploit this?

An attacker needs to cause a request to receive a cross-origin 307 or 308 redirect to an attacker-controlled server. The redirected request can then include caller-supplied custom headers, excluding only headers that reqwest classifies as sensitive.

3

Is the default HTTP client configuration affected?

Yes. The described default_http_client() builds a reqwest client without overriding its redirect policy, leaving reqwest's default limited(10) redirect behavior in place. That behavior follows 307 and 308 redirects and does not treat custom authentication headers as sensitive.

4

How can I determine whether my use is exposed?

Review whether StreamableHttpClientTransportConfig.custom_headers is populated with credentials or other secrets, and whether requests can be redirected to a different origin. The advisory identifies commit c330fede90e4729c234f8e87fdbc5ea27a1dd10c as tested, but does not provide an affected version range.

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203