How the OWASP LLM Top 10 Maps to MCP Deployments
How prompt injection becomes tool poisoning and indirect injection via tool output in MCP. LLM01:2025 is the prompt injection …

How prompt injection becomes tool poisoning and indirect injection via tool output in MCP
LLM01:2025 is the prompt injection category: attackers manipulate model inputs to override original instructions, either directly from user input or indirectly from external content the model retrieves. MCP doesn't just preserve this risk. It relocates it somewhere most input-validation frameworks were never designed to look.
At session initialization, the model reads tool descriptions, parameter schemas, and structured metadata from the MCP server. Those fields look like configuration to a developer. To the model, they are instructions. That distinction is the root cause of MCP03, Tool Poisoning. Two CVEs from 2025, CVE-2025-54136 (MCPoison) and CVE-2025-54135 (CurXecute), proved this through different exploit paths but the same structural failure: tool metadata treated as trusted content by the model, because nothing in the protocol marks it otherwise.
Indirect injection via tool output, MCP04, is more dangerous precisely because it looks more legitimate. The server embeds adversarial instructions inside a tool's return value. The LLM receives that output as trusted context and acts on the embedded instructions, often without any visible signal to the user. No anomalous request. No suspicious input. Just a tool doing what tools do, except the payload is riding along inside the response.
The DockerDash attack makes this concrete. An agent called docker_inspect on a container image. The image's LABEL field contained injection instructions. The LLM stopped three running containers and then generated a false "all clear" report. The attack traveled entirely through a legitimate tool call; no suspicious network traffic, nothing a conventional WAF would have flagged. Invariant Labs documented a WhatsApp MCP server in 2025 that ran cleanly on initial launches, injected its payload on subsequent calls, and then reverted, leaving no persistent trace in logs. The attack was designed to be boring. Boring, in this context, is the point.
OWASP is candid about why this resists easy remediation: traditional input validation is ineffective here because the model itself is the exploited component, not the application logic surrounding it. You cannot sanitize your way out of a problem where the channel you need to sanitize is the model's own context window. The fix isn't another regex. That's uncomfortable, because it forecloses a class of solutions people reach for instinctively.
Controls belong in three places. Inspect tool metadata at registration and flag schema fields containing natural-language instruction patterns before the model ever sees them. Treat tool output as untrusted data before it re-enters the model, not after something breaks. And draw a hard, written line between tools the model can call autonomously and tools that require a human to confirm before execution. That line needs to exist somewhere other than someone's mental model of the system.
Where sensitive data leaks in MCP: tokens in memory, secrets in logs, and context that outlives its task
LLM02:2025 covers sensitive information disclosure. In MCP, this risk has a more prosaic and more immediate form than training-data memorization.
MCP01 is Token Mismanagement and Secret Exposure. The typical path is almost mundane: a developer commits an API key during a testing sprint; the MCP server reads it from a config file at startup; an AI assistant surfaces it in a response to a routine query. Nobody made a dramatic mistake. The key just traveled further than anyone tracked. Weak session handling compounds this. Long-lived, improperly scoped session tokens let an attacker replay messages or impersonate a legitimate client without triggering detection. By January 2026, over two thousand exposed MCP instances were leaking API keys and conversation histories to anyone running a Shodan search. Not a sophisticated attack. An unauthenticated gateway and patience.
MCP10, Context Over-Sharing, is subtler and, in some ways, more corrosive. Context windows accumulate prompts, retrieved data, and intermediate outputs across a session. In multi-tenant or multi-agent deployments, a context that isn't aggressively scoped and cleared becomes a leakage channel. One agent's working memory becomes another's attack surface. The information doesn't need to be extracted; it just needs to persist longer than the task that generated it, which, left unmanaged, it does. Every session you don't explicitly close is a window you've left open.
The controls are less glamorous than the attacks, which is probably why they get deferred. Short-lived, scoped credentials at the server level. Secret-scanning at startup. Nothing written to protocol logs that you wouldn't want in a breach report. Context scoped to the task and cleared at termination. Tenant isolation enforced at the connection level, not assumed from application logic above. Audit every tool invocation that touches credentials, and build real-time alerting on anomalous data-retrieval patterns. A log you read after the incident is a postmortem. That's different from a control.
MCP's supply chain problem: rug pulls, package squatting, and tools that change after you approved them
LLM03:2025 is supply chain vulnerabilities. MCP has an analog in MCP05, Supply Chain Compromise, but it also introduces a vector that doesn't map cleanly onto anything in traditional software supply chain thinking.
The rug pull is MCP's most distinctive threat. A server silently alters a tool's definition or behavior after a developer has already reviewed and approved it. Most MCP clients verify tools at install time. They do not re-alert when definitions change. The agent keeps calling what it believes is a trusted tool while executing a version that has been quietly modified. One security researcher put it plainly: "Your AI agent's tools can change after you approve them, without triggering any notification or re-consent. The MCP spec allows this by design." That last phrase is the one worth stopping on. If the spec allows silent redefinition, what does "approved" actually mean?
Three incidents illustrate the shape of the problem. The postmark-mcp squatting attack in September 2025 involved a fake npm package that built trust through fifteen incremental versions before silently BCC'ing all outbound emails to an attacker. Slow, deliberate, nearly invisible until someone noticed the traffic. The Clawdbot exposure in January 2026 revealed more than two thousand MCP instances leaking credentials and conversation histories through unauthenticated gateways. A GitHub MCP prompt injection campaign hijacked agents into exfiltrating private repository data by embedding malicious instructions in GitHub issues the agent was authorized to read. That one is particularly pointed, because the authorization was entirely legitimate. The agent did exactly what it was permitted to do.
Researchers at Cisco have formally classified rug pull and tool squatting as primary MCP threat categories, proposing cryptographic signing of tool definitions, immutable versioning, and OAuth-scoped capabilities as mitigations. None of those controls exist in the base protocol. That's not a criticism of Anthropic; MCP was designed for interoperability, and security constraints tend to arrive after adoption does. But it means the controls have to be added by you, deliberately, because the protocol won't add them for you.
A registry that tracks every registered MCP server and flags definition changes is the right starting point. Cryptographic signing makes definition drift detectable after the fact. Re-consent workflows triggered by tool definition changes, not just by initial installation, close the gap the rug pull exploits.
Data and model poisoning in MCP: how corrupted embeddings and retrieval pipelines feed bad context to agents
LLM04:2025 addresses data and model poisoning; LLM08:2025 covers vector and embedding weaknesses. In MCP, these two categories converge through the Resource primitive, and that convergence has implications most teams haven't fully absorbed.
Agents call Resources to retrieve context. Those resources frequently include vector stores and RAG pipelines. When an agent retrieves content from a vector store, it has no internal mechanism to distinguish legitimately stored content from content an attacker injected. The attack path is structurally clean: an attacker writes malicious content into a document, database, or vector store the MCP server is authorized to read; the agent calls the Resource; the poisoned content arrives as trusted context and shapes downstream tool calls or model outputs. The model's behavior is manipulated without touching the model itself. If you've spent real time hardening your model and its training pipeline, that should land with some weight.
Cross-tenant embedding exposure connects this to MCP10, Context Over-Sharing. Where vector stores are shared across users or agents without strict per-query access controls, one tenant's query can surface another's data. The retrieval layer becomes the leakage mechanism, quietly, and usually without anyone intending it to be.
The controls require architectural decisions that are easy to defer and genuinely hard to retrofit. Access controls on vector stores must be enforced at query time, not assumed from application-layer logic sitting above the MCP layer. Monitor retrieval patterns for anomalous cross-boundary data access, specifically the kind of query that returns data from a namespace the requesting agent was never supposed to reach. Scope Resource permissions to the specific data domains each agent legitimately needs, not to everything the server can technically access. "We'll scope it later" is a reasonable thing to say during a sprint. In security, later has a way of not arriving.
Improper output handling and command injection: when MCP tool output reaches a downstream system unvalidated
LLM05:2025 is improper output handling: model output passed to downstream systems without validation, enabling injection attacks, SSRF, or remote code execution. MCP doesn't just make this more common. It makes it structurally more dangerous, because the output isn't going to a screen.
In a standard LLM application, output goes to a user interface. A human reads it. Even if the output is subtly wrong, the human is a checkpoint. In MCP, output can directly trigger another tool call, a shell command, or an external API request. The model's output is an executable instruction. Chained tool calls amplify this: one tool's output becomes the next tool's input, with no human review between them and no moment where unvalidated content is examined before it causes a real-world action. The architecture is elegant. That elegance is also the exposure.
DockerDash illustrates LLM01 and LLM05 simultaneously, which is why it keeps coming up. The injection that arrived through the tool's return value produced no misleading response a user would have caught. It caused the agent to stop running containers, then generated a false report to cover it. Infrastructure modification, triggered by unvalidated output from a legitimate tool call. That sequence is not exotic. It's what happens when output validation is treated as optional.
At the server, treat all tool output as untrusted before it re-enters the model or triggers a downstream call. The server should not assume its own output is safe simply because it produced it; that assumption is precisely what attackers rely on. At the gateway, enforce output schema validation and block tool-call chains that exceed defined depth or cross unauthorized system boundaries. For tool calls that execute shell commands or make external API requests based on prior tool output rather than direct user instruction, require explicit confirmation. That confirmation is friction. It is also the only human checkpoint in an otherwise automated chain, and removing it to improve velocity is a tradeoff worth naming explicitly before you make it.
Excessive agency in MCP: what happens when an agent can reach tools it should never have been able to call
LLM06:2025 breaks excessive agency into three root causes: excessive functionality, excessive permissions, and excessive autonomy. MCP makes all three the default rather than the exception, and that's a design consequence worth being honest about.
MCP servers expose all registered tools to any connected client. The protocol has no built-in least-privilege model. Developers typically register everything a server offers, intending to scope access later. The full attack surface exists from the moment the server goes live. MCP02, Scope Creep and Over-Privileged Access, captures what follows: temporary or loosely defined permissions expand over time; an attacker who finds weak scope enforcement can perform actions the developer intended to prevent, including repository modification, system control, and data exfiltration. The capability was there from the start. Nobody drew the line.
MCP09, Shadow MCP Servers, compounds this at the organizational level. Developers and research teams spin up unapproved MCP instances with default credentials and permissive configurations, operating entirely outside governance. The organization has no record of what tools those servers expose, no audit trail of what they've been asked to do, and no mechanism to revoke access if something goes wrong. Shadow IT is not a new problem. But the blast radius of a shadow MCP server is considerably larger than a shadow Dropbox folder, because the tools it exposes can write code, modify infrastructure, and call external APIs.
Some would argue that RBAC for AI agents is just standard access control rebranded. That framing misses something important. Restricting what an agent can reach is about ensuring that what the agent can do reflects a deliberate organizational decision, not a permission inherited from a default configuration and never reviewed. The capability exists either way. The question is whether anyone chose to grant it. In most MCP deployments today, the honest answer is that no one did. It was simply never revoked.
Maintain a registry of every MCP server and every tool it exposes. Treat anything outside that registry as untrusted by default. Scope tool registration to task-specific needs at deployment time, not as something to revisit after the sprint closes. Enforce human-in-the-loop confirmation for tool calls that write data, execute code, or modify infrastructure. The goal isn't to slow agents down. It's to ensure that when an agent acts, it acts within boundaries someone in your organization explicitly drew, on a day they can name, for a reason they can articulate.


