Skip to content

[GHSA-m5pj-3536-3xcp] - [v2] - MCP Inspector v2.7.0 — /api/fetch proxy has no size cap on the proxied response body (memory-exhaustion DoS) #2780

Closed

Description

@cliffhall

Advisory: GHSA-m5pj-3536-3xcp

Affected versions: @modelcontextprotocol/inspector <= 2.7.0

Reporter: @CloneOfAlex

Severity: high | Reported: 2026-09-18

Priority score (2026-10-20, post-verification): Severity 3, Urgency 4, +1 security, Total 8 → Medium. Affected: v2 2.0.0–2.11.0 and v1. Accepted 2026-10-20.


Summary

/api/fetch — the browser's only way out to the network for MCP traffic and OAuth work — reads the upstream response with a non-streaming await res.text() and no byte cap, then re-serializes the entire body into a JSON envelope sent to the browser (which parses it a third time). This allows an untrusted or misbehaving MCP server (or an OAuth/CIMD redirect target) to exhaust the Inspector backend process's memory with a very large or unbounded response body.

Details

  • Location: core/mcp/remote/node/server.ts, POST /api/fetch handler (~line 1206–1367); client-side deserialization in core/mcp/remote/createRemoteFetch.ts.
  • CWE: CWE-400 (Uncontrolled Resource Consumption) / CWE-770 (Allocation of Resources Without Limits or Throttling).
  • Affects: v2 (@modelcontextprotocol/inspector), all versions up to and including 2.7.0. v1 was not reviewed.

The handler destructures {url, method, headers, body, timeoutMs} from client JSON, checks only if (!url), then does (createProxyFetch() ?? fetch)(url, {...}) and reads the full response body via res.text() with no size limit before re-encoding it into JSON. Contrast this with the same file's sibling /api/app-document route, which enforces MAX_APP_DOCUMENT_BODY_BYTES (24MB) via hono's bodyLimit middleware before parsing — its own comment explains why: "an unbounded body ... is fully materialized in memory before being rejected." That discipline was not applied to /api/fetch.

This was found via a static source-code review of the publicly tagged 2.7.0 release (commit 2e90a62) — no live exploit was executed against a running instance.

PoC

  1. Point Inspector at (or get redirected during OAuth to) a server that streams an arbitrarily large or slow-drip response body.
  2. Trigger any request that flows through /api/fetch (an MCP call, or OAuth discovery/token exchange).
  3. Observe the Node backend's memory grow unbounded while res.text() reads the full body before any check is applied.

(Static review basis — no live run was performed to measure actual memory growth.)

Impact

A user points Inspector at a remote or misbehaving MCP server that returns a very large or effectively unbounded response body. That body is buffered fully in the Inspector Node process's memory, re-encoded into a JSON string (roughly doubling the memory footprint), sent to the browser, and parsed a third time — squarely within Inspector's own threat model of inspecting untrusted/misbehaving MCP servers. The team has already demonstrated awareness of this exact pattern by fixing it on the neighboring /api/app-document route.

Suggested fix: apply the same discipline as /api/app-document — cap the proxied response body size (stream-and-truncate, or reject once a threshold is exceeded) before buffering it into memory or re-encoding it into the JSON envelope.

Activity

  1. added
    v2Issues and PRs for v2
    bugSomething isn't working
    on Oct 22, 2026
  2. added this to the v2.12.0 milestone on Oct 22, 2026
  3. changed the title [-][GHSA-m5pj-3536-3xcp] - MCP Inspector v2.7.0 — /api/fetch proxy has no size cap on the proxied response body (memory-exhaustion DoS)[/-] [+][GHSA-m5pj-3536-3xcp] - [v2] - MCP Inspector v2.7.0 — /api/fetch proxy has no size cap on the proxied response body (memory-exhaustion DoS)[/+] on Oct 22, 2026
  4. cliffhall commented on Oct 22, 2026

    @cliffhall
    MemberAuthor

    Shipped in 2.12.0, published to npm under latest. Advisory: GHSA-m5pj-3536-3xcp.

    Landed on v2/main in merge commit 4862b746, and reached main through the milestone merge #2769 (0cac110a). The fix commits:

    • 3d701a0b fix(web): cap the /api/fetch response body
    • 53d1c62e fix(web): relay an error status whose /api/fetch body is over the cap

    A follow-up found in the release smoke also shipped in 2.12.0: #2771, fixed by #2774 (cbb3c656 fix(web): drop the dropped body's framing headers from an oversize error relay).

    The v1 half is #2781 and shipped in 1.0.3.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingv2Issues and PRs for v2

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions