[RIP-SEC] MCP client does not cap the HTTP/SSE response body on the default (Legacy) request, allowing a malicious MCP server to exhaust client memory
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 68/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- rust
- Domain
- networking, security
Research direction
Start in codex-rs/rmcp-client/src/http_client_adapter.rs with the maximum_response_bytes selector and collect_body, then read the cap constant in codex-rs/rmcp-client/src/local_stdio_transport.rs. Verify that the default/Legacy HTTP/SSE path enforces the intended cap and that an oversized body produces ResponseTooLarge rather than being fully collected.
Written by the indexing model from the issue text.
Description
Summary
The rmcp HTTP transport applies its 8 MiB response cap (MAX_MCP_STDIO_LINE_BYTES) only when the
request is the capability Discover method or carries the modern protocol-version header
(2026-07-28). For the default/Legacy request the limit is None, and the body collector appends
every chunk with no ceiling. A malicious or MITM'd MCP server can return an arbitrarily large
HTTP/SSE body and exhaust the client's memory. The stdio transport caps at 8 MiB and enforces it,
showing the bound is intended.
Where
codex-rs/rmcp-client/src/http_client_adapter.rs:
let maximum_response_bytes = (mcp_method.as_deref() == Some(DiscoverRequestMethod::VALUE)
|| headers.get(HEADER_MCP_PROTOCOL_VERSION).and_then(|v| v.to_str().ok())
== Some(ProtocolVersion::V_2026_07_28.as_str()))
.then_some(MAX_MCP_STDIO_LINE_BYTES); // None on the default/Legacy path
collect_body (same file) skips the size check entirely when maximum_bytes is None. Cap constant:
codex-rs/rmcp-client/src/local_stdio_transport.rs. Present on current main.
Reproduction
Exercising the exact cap selector and collect_body logic: for a Legacy request the computed limit is
None; collect_body(16 MiB, None) returns the full 16 MiB (unbounded) while
collect_body(16 MiB, Some(8 MiB)) returns ResponseTooLarge. In production the stream length is
attacker-controlled and unbounded.
Impact
Memory-exhaustion denial of service against a Codex client that connects to a malicious/MITM MCP
server over the default HTTP transport. DoS only — no code execution or data exposure.
Suggested fix
Apply the cap on all HTTP/SSE MCP responses (default maximum_response_bytes to the cap and widen it
deliberately), rather than defaulting to None for Legacy requests.
Found with the rust-in-peace pipeline
(AI-assisted Rust vulnerability research).
- Dominant language
- Rust
- Stars
- 125k
- Forks
- 19.5k
- Avg merge
- 1m
- Merged PRs (30d)
- 1k
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openai/codex
-
enhancement remote
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
bug CLI windows-os
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
macOS sandbox blocks hw.optional.arm64 sysctl, causing Flutter to misdetect Apple Silicon as x64 Openbug CLI sandbox
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
bug CLI TUI
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
CLI config enhancement skills
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
gitbutlerapp/gitbutler#15998 · 1 comment ·
-
bug triage:deciding
Difficulty 1/5 Under an hour Newbie friendliness 88/100
open-telemetry/otel-arrow#4132 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
bitcoindevkit/bdk-ffi#1125 ·