Logan Kelly
NSA guidance says MCP tool outputs are never implicitly trusted. Request-time authorization misses the return path — here's what to govern instead.

In May 2026 the NSA's Artificial Intelligence Security Center published a Cybersecurity Information Sheet on the Model Context Protocol. One of its recommendation headings is "Filter and monitor output pipelines and chained execution," and the first sentence under it is blunt: "Outputs from tools and models should never be treated as implicitly trusted, even if they originate from previously vetted components."
The natural place to put a control is the outbound leg: may this agent call this tool with these arguments. That question is fully answerable at dispatch time, which is what makes it attractive — and also what makes it insufficient. The content that comes back is easy to treat as data in transit: logged, traced, sometimes redacted, but not necessarily subjected to a policy decision of its own.
MCP tool output security is the practice of treating what an MCP server returns as untrusted input to the next stage of the agent pipeline, subject to its own policy decision, rather than as the trusted result of an already-authorized request. It applies to the content, embedded resources, and resource links a tool hands back before that material enters the model's context.
The distinction matters because a tools/call is not a request with a receipt. It is a request with a payload of model-visible content attached to the reply, and that payload is the part an attacker actually wants to control.
Why is the return path structurally different?
Authorization answers a question at one instant: at dispatch time, given this identity, this tool, and these arguments, allow or deny. It is a decision about intent.
The return leg carries content — and content is the substrate the model reasons over. Once a tool result is placed in the context window, the model does not distinguish between instructions that came from the user and instructions that arrived inside a search result, a file body, or an error string. This is the indirect prompt injection problem, and the NSA CSI names it directly, recommending that "output filtering should include detection of indirect prompt injection or toolchain pivot attempts."
The asymmetry is architectural, not a maturity gap. A request-time gate can be made complete with respect to intent, because intent is fully described by the call. It cannot be made complete with respect to content, because the content does not exist yet when the decision is made. Governing the request well tells you nothing about what came back.
What can actually arrive in a tool result?
The MCP specification is more permissive here than a request-centric threat model would suggest. A tool result is not a string. Per the current specification, unstructured content in a result may be text, image, audio, resource links, or embedded resources — and an embedded resource inlines an entire document body directly into the result, complete with its URI and MIME type. A structuredContent object may travel alongside it.
Two properties deserve attention from anyone building a control here.
The first is that tool results can hand the client a pointer to material the server never advertised. The specification states plainly that "Resource links returned by tools are not guaranteed to appear in the results of a resources/list request." An inventory built by enumerating a server's advertised resources is therefore an incomplete picture of what that server can put in front of a model. The tool call is its own discovery channel.
The second is that result content carries annotations — including an audience field marking material for the user, the assistant, or both, and a priority value. That metadata is supplied by the server. The specification already warns that clients "MUST consider tool annotations to be untrusted unless they come from trusted servers," which is precisely the judgement a governance layer exists to stop making case by case.
Who does the specification make responsible?
This is where the design becomes uncomfortable. Under Security Considerations, the current specification assigns servers a MUST: sanitize tool outputs. Clients get a SHOULD: validate tool results before passing to LLM.
Read those two obligations against the deployment reality. The server is the third party — the upstream you did not write, do not run, and cannot audit on demand. The stronger obligation for output safety sits with the party the consuming organization has the least control over. The client, which is the party actually exposed to the consequences, gets the weaker verb and no prescribed mechanism.
Note also the contrast on the request side, where the same list tells clients to "Show tool inputs to the user before calling the server, to avoid malicious or accidental data exfiltration." There is a human-visible checkpoint specified for arguments going out. Reading that list of client obligations in full, it specifies no equivalent step for content coming back.
What does the measured server population look like?
A July 2026 assessment by Nicolás Padilla, published on arXiv as "Exposed by Design," gives some shape to the upstream population these obligations rest on. The study identified over 21,000 MCP server instances detectable on the public internet, confirmed 640 production servers, and dynamically audited 414 of them using a purpose-built framework covering ten MCP-specific vulnerability classes.
Three findings bear on the return path. The audit uncovered 68 reportable vulnerabilities, including prompt template injection — a defect class whose output is, by construction, content that flows back toward a model. It found 687 tool instances across confirmed servers exposing shell execution capabilities without access controls. And it found that 41.6% of confirmed servers disappeared within three days between consecutive measurement runs.
That last number is the one worth sitting with. A trust relationship with an upstream assumes there is a stable counterparty to trust. When a substantial fraction of the observed population turns over inside seventy-two hours, "we vetted this server" is a statement with a short and unpredictable shelf life — and the vetting that matters most is of the thing the server sends back.
The NSA CSI frames the same point as a systems property rather than a checklist item: "These are not isolated problems that can be patched at the interface or endpoint level. Securing MCP systems requires treating the agentic environment as a continuum." A continuum has two directions.
How Waxell handles this
The Waxell MCP Gateway evaluates a tools/call twice. Calls that traverse the gateway are policy-checked before dispatch, and the result is evaluated again before it returns to the agent. Coverage is a configuration property, not an automatic one — agents holding direct upstream credentials or pointing at unconfigured servers bypass the gateway entirely, and a governance claim is only as good as what is actually routed through it.
On the return leg, the policy engine exposes actions that act on results rather than arguments. redact_result strips named keys from a result. dlp_scan_result runs DLP scanners for PII and credentials and records findings. dlp_block_result blocks the result when those scanners hit. egress_block blocks results containing URLs or hosts outside an allowlist — a control aimed squarely at the exfiltration half of the problem, where a poisoned result tries to route data to an attacker-chosen destination.
The distinction between scanning and blocking is deliberate and is reflected in the documented starter rule set, which recommends dlp_scan_result on everything for visibility first, then upgrading specific hot spots to dlp_block_result once real traffic has been observed. Detection and enforcement are separate decisions; conflating them is how teams end up believing they have a control they have not switched on.
On the request side, tool descriptions are scanned for embedded instructions at fingerprint time, before an agent calls the tool, and the gateway can deny a tool whose fingerprint has changed since it was last approved via a deny_drift rule — recommended in the starter set rather than enabled by default. Decisions on both legs — what was allowed, denied, redacted, and which rule fired — land in the gateway's tool-call audit log, which records the decision without retaining argument values or result bodies, and exports to CSV.
FAQ
Is MCP tool output security different from prompt injection defense?
It is the delivery channel for one variety of it. Indirect prompt injection is the attack; the tool result is one of the main routes that attack takes into an agent's context. Treating output as a governed surface addresses the route rather than trying to make the model immune to the payload, which is why the NSA CSI recommends output filtering as a pipeline control instead of a model property.
Does validating tool results mean reading everything the agent sees?
Not necessarily, and there is a real privacy tension in assuming it does. A policy decision can be made on a result without persisting it — scanning for credential patterns or blocking on disallowed egress hosts operates on content in flight. Waxell's gateway audit log is built on that separation: it records the decision and the rule that fired without storing argument values or result bodies.
Why does the MCP specification put output sanitization on the server?
The specification is written for protocol implementers on both sides, and a server genuinely is best placed to sanitize what it produces. The difficulty is deployment rather than drafting: in practice the server is a third party, so an obligation placed there is one the consuming organization cannot enforce or verify. That gap is what a client-side or gateway-side control exists to close.
What is the practical first step for a team already running MCP in production?
Inventory what is actually routed where, then turn on result-side scanning in report-only mode before enforcing anything. Real traffic reveals which tools return sensitive material and which return content from sources the team did not expect, and both answers are usually surprising. Enforcement decisions made before that data exists tend to be either too loose to matter or tight enough to break working agents.
Do resource links returned by a tool show up in a server's resource listing?
Not reliably. The specification states that resource links returned by tools are not guaranteed to appear in the results of a resources/list request, which means an inventory built only from advertised resources can miss material a tool can surface. Any coverage claim based on enumerating a server's resource list should be scoped accordingly.
Sources
National Security Agency, "NSA Releases Security Design Considerations for AI-Driven Automation Leveraging the Model Context Protocol" (press release), May 20, 2026
National Security Agency Artificial Intelligence Security Center, "Model Context Protocol (MCP): Security Design Considerations for AI-Driven Automation" (Cybersecurity Information Sheet, Ver. 1.0), May 2026
Model Context Protocol, "Tools — Server Features" (specification version 2026-07-28)
Padilla, Nicolás, "Exposed by Design: A Dynamic Security Assessment of Internet-Facing MCP Servers at Scale," arXiv:2608.00150, July 31, 2026
Waxell, "Policies & Approvals," Waxell MCP Gateway documentation
Get started
Start free with the Waxell MCP Gateway and one governed MCP upstream, including 10,000 traced executions a month on the free plan — sign up here and route your first upstream through a gateway that evaluates the answer as well as the question.
Agentic Governance, Explained




