{"slug":"mcp-security-control-layers","title":"What actually breaks when you run MCP in production, and how do you defend it?","question":"What actually breaks when you run MCP in production, and how do you defend it?","summary":"Documented MCP CVEs cluster in four layers: unsafe tool execution, unauthenticated management endpoints, unrestricted outbound calls, and undetected tool-definition drift. A gateway defends none of them directly; each needs its own control, enforced closer to the failure.","status":"active","cluster":"safety","cluster_label":"Safety and control","updated":"2026-10-07","latest_evidence_added":"2026-10-07","audience":"strong-software-engineer","math_depth":"","sections":[{"heading":"Builder consequence","html":"<p>If &quot;securing MCP&quot; means &quot;put it behind an authenticated gateway,&quot; you have covered one layer of four. Documented MCP CVEs mostly happen inside or behind the server the gateway fronts: how a tool executes arguments, what the server can reach outbound, and whether a tool&#x27;s definition still matches what was approved. A gateway&#x27;s inbound auth check inspects none of these.</p>"},{"heading":"Short answer","html":"<p>MCP vulnerabilities cluster into four layers, each stopped at a different point:</p>\n<ul><li><strong>Execution</strong> — arguments reach a shell or <code>eval()</code>.</li><li><strong>Management</strong> — inspectors, test harnesses, and registration endpoints left unauthenticated.</li><li><strong>Outbound trust</strong> — a server can call any URL with a privileged credential.</li><li><strong>Semantic integrity</strong> — a tool&#x27;s definition changes after approval.</li></ul>\n<p>A gateway is an inbound routing and auth control. Three of the four failures happen behind it.</p>"},{"heading":"Builder model","html":"<p>Model each MCP server as a small privileged service with its own attack surface, not a trusted host inside a gateway perimeter. Ask four questions:</p>\n<ol><li>Does it turn caller arguments into a shell command or evaluated code?</li><li>Are its non-agent interfaces (debug, CI, registration) authenticated?</li><li>What can it reach outbound, and with which credential?</li><li>Can its advertised behavior change without anyone noticing?</li></ol>\n<p>A gateway answers &quot;who may call this server,&quot; a real but separate question.</p>"},{"heading":"Mechanism","html":"<p><strong>Execution.</strong> A tool passes caller-controlled arguments into a shell string or <code>exec()</code>/<code>eval()</code>: classic command injection, reached through a tool call instead of a web form. The InfoQ analysis attributes <strong>13 of 30</strong> documented CVEs to this. Argument arrays leave nothing to inject into.</p>\n<p><strong>Management.</strong> MCP tooling ships operational surfaces built with dev-tool casualness and left reachable on production networks. Six CVEs are unauthenticated endpoints that should not have been reachable at all.</p>\n<p><strong>Outbound trust.</strong> Unrestricted egress plus a broad credential turns one SSRF into credential theft. CVE-2026-26118 let a malicious URL pull an Azure managed-identity token because nothing constrained the destination or scoped the token.</p>\n<p><strong>Semantic integrity.</strong> In a &quot;rug-pull,&quot; the tool a reviewer approved is not the tool that later executes, because the server&#x27;s advertised definition changed. Pinning a canonical hash of the approved definition turns any change into an explicit review event.</p>"},{"heading":"How to apply","html":"<ul><li><strong>Audit execution paths first; it is the largest CVE category.</strong> Grep for <code>shell=True</code>, <code>exec()</code>, <code>eval()</code>, and string-built commands; require argument arrays and fail CI on violations.</li><li><strong>Treat inspectors, test harnesses, and registration endpoints as production services</strong>, with authentication, network isolation, and minimal filesystem access.</li><li><strong>Put an egress allow-list on every server and scope credentials per tool purpose</strong>, so one leaked token cannot reach everything the server can.</li><li><strong>Pin tool manifests at registration</strong> with a SHA-256 hash of the canonical definition, and require operator review for any material change.</li><li><strong>Add input and context scanning on tool schemas and outputs.</strong> COPEX measured a 49.6% mean drop in attack success on an eight-attack subset; it is a mitigation, not a replacement for the controls above.</li><li><strong>Budget for controls beyond the gateway.</strong> It provides inbound routing, auth, and observability; execution, outbound, and integrity controls are separate work.</li></ul>"},{"heading":"Failure modes","html":"<ul><li>Equating &quot;behind an authenticated gateway&quot; with &quot;secure.&quot;</li><li>Leaving debug or inspector tooling reachable because it &quot;isn&#x27;t the real API.&quot;</li><li>Giving a tool an outbound credential broader than its one integration, so an SSRF becomes full-credential exfiltration.</li><li>Trusting a server&#x27;s current tool definition indefinitely after first approval.</li></ul>"},{"heading":"Related","html":"<p>See <a href=\"/topic/mcp\">MCP</a>, <a href=\"/topic/agent-sandboxing\">agent sandboxing</a> for execution isolation that complements argument arrays, and <a href=\"/topic/prompt-injection\">prompt injection</a> for the attacker-controlled input behind outbound-trust failures.</p>"}],"evidence":[{"id":"copex-2026-mcp-adversarial-context","kind":"benchmark-result","tier":"benchmark/result-backed","title":"COPEX: Benchmarking LLM Robustness to Adversarial Context Across Model Context Protocol Layers","note":"Holds the agent stack fixed and varies only the tool-selecting model: 25 attack types, 125 scenarios, four entry surfaces (model/agent, client, server/tool, transport), nine models, 3,375 trials. Mean attack success is 64.4%, 58.3% to 71.4% by surface. Some client and transport attacks succeed outside the model's view. Combined input and context scanning cut mean success 49.6% on an eight-attack subset.","added":"2026-10-07","url":"http://arxiv.org/abs/2610.04378v1","sid":"b0a6adb95dddda44"},{"id":"infoq-mcp-defense-in-depth","kind":"production-field-report","tier":"production field-report-backed","title":"Securing MCP in Production: Defense-in-Depth Beyond the Gateway","note":"Groups 30 documented MCP CVEs into four layers: 13 from unsafe execution (shell interpolation, exec/eval on input), six from unauthenticated inspector, test-harness, or registration endpoints, outbound trust (CVE-2026-26118, an Azure SSRF leaking a managed-identity token), and post-registration definition drift ('rug-pull'). Recommends argument arrays, authenticated and isolated management endpoints, egress allow-lists with per-purpose credentials, and SHA-256 manifest pinning with operator review.","added":"2026-08-08","url":"https://www.infoq.com/articles/securing-mcp-production-gateway/"},{"id":"aws-agentcore-mcp-2026-07-28-spec","kind":"story","tier":"source story","title":"How AgentCore Gateway supports the MCP 2026-07-28 spec","note":"Context: the hardening guidance landed one day after MCP's 2026-07-28 spec revision, which changed authorization but left execution, management, outbound, and integrity risks to deployment-level controls.","added":"2026-08-08","sid":"b734d716b0d66f96"},{"id":"mcp-security-editorial-synthesis","kind":"editorial-inference","tier":"editorial inference","title":"LLM Digest synthesis","note":"A routing gateway sits at the network edge, while three of the four failure classes (unsafe execution, outbound exfiltration, definition drift) originate inside or behind the MCP server. A gateway enforces inbound auth and rate limits but cannot see what a tool does once a call reaches it.","added":"2026-08-08"}],"related_topics":[{"slug":"mcp","title":"Model Context Protocol: a standard interface for agent tools"},{"slug":"agent-sandboxing","title":"Sandboxing, scoped credentials, and guardrails"},{"slug":"prompt-injection","title":"Untrusted input and tools can hijack an agent"}],"related_playbook_cards":[],"related_storylines":[]}