Topic · MCP Security

Tool Poisoning

Crawdad Security·Published ·Updated
In short

Tool poisoning is an attack on AI agents in which malicious instructions are hidden inside the description or schema of a tool the agent uses, causing the agent's underlying model to follow the attacker's instructions instead of the user's. Because the model reads a tool's description as trusted context — at the same privilege level as its own system prompt — a poisoned description can direct the agent to read sensitive files, exfiltrate data, or misuse other tools, all while displaying a benign name like “Adds two numbers” to the user.

Tool poisoning was first named and demonstrated by Invariant Labs in April 2025 and is now considered the most prevalent and impactful client-side vulnerability in the Model Context Protocol (MCP) ecosystem.

Key facts

How does tool poisoning work?

An AI agent connects to an MCP server and requests its available tools with a tools/list call. The server returns a JSON document describing each tool: a name, a description, and an input schema. The model reads that description directly, because it needs it to decide how and when to use the tool. The description is, in effect, instructions to the model.

In a tool-poisoning attack, the description carries hidden instructions. Invariant Labs' original proof of concept used a tool named “add” whose description read, in part: “Adds two numbers.” followed by a hidden block instructing the model, before using the tool, to read the user's SSH private key and MCP configuration file and pass their contents through an extra parameter to the attacker's server. In the editor, the tool displayed only as “Adds two numbers.” The model saw the full description and complied — reading the private key and exfiltrating it. The user had asked the agent to add two numbers.

Why is tool poisoning so hard to defend against?

The instructions do not have to be visible to be effective. Because the model reads the raw text while the user sees a simplified display, attackers can conceal the payload using techniques that defeat visual inspection: Unicode “tag” codepoints that render as nothing, whitespace padding that pushes the payload past a UI's scroll cutoff, truncation gaps between what a client displays and what it sends to the model, homoglyphs, and zero-width characters. Scanning a tool's description for obvious malicious text is worth doing but cannot be the primary defense, because the payload can be made invisible to the scanner just as it is to the user.

The deeper reason is a trust gap in the protocol's design. Tool descriptions are reviewed, if at all, once — at connect time. Tool responses, returned on every call at runtime, flow into the model's context with no equivalent check. There are two channels by which attacker-controlled text reaches the model at system-prompt trust, and only one is inspected.

How is tool poisoning different from prompt injection?

Prompt injection is the general class of attack in which untrusted input causes a model to follow embedded instructions. Tool poisoning is a specific form of indirect prompt injection where the untrusted input arrives through the tool channel — the description or schema of an MCP tool — rather than through a user message or an ingested document. The distinguishing feature is that the poisoned tool is often presumed trusted (it may be a popular, widely used server), and the payload can manipulate the agent's use of other trusted tools, making the compromise broader than a single injected instruction.

How do you defend against tool poisoning?

Recommended controls include pinning and reviewing tool definitions (treating a change to a tool description as a dependency update that warrants review, as Microsoft's 2026 guidance proposes), signed tool manifests, scanning tool metadata for embedded instructions, and limiting an agent to only the tools a given session requires. These reduce exposure at the description layer.

The layer these controls do not cover is runtime behavior. Whatever a poisoned description instructs, and however it is hidden, the harm is the concrete action it induces — reading a sensitive file, sending data to an external host. That action is the same whether the payload was plaintext or obfuscated. A runtime control positioned on the agent's actual traffic sees the file read and the egress as concrete events, independent of how the tool description that triggered them was written or concealed. Inspecting the action, rather than the instruction, is the defense that obfuscation cannot evade.

How Crawdad addresses tool poisoning

Crawdad is a runtime security layer for AI agents that inspects every action an agent takes on the wire, on the device where the agent runs. Because it evaluates the concrete action — the file read, the tool call, the network egress — rather than only the tool description, it is not defeated by a payload hidden in a description's Unicode or whitespace. Crawdad publishes a public, reproducible benchmark of contemporary agent attacks, including tool-abuse and supply-chain manipulation categories, under an open license.

See the Crawdad technical paper The Agentic Attack Surface for a full treatment of the tool-poisoning mechanism.

Reference pages for Prompt Injection, the OWASP Agentic Top 10, and Runtime Agent Security are being added to the Topics section.

Primary sources