Blog / 31 October 2026
Deep dive · 31 October 2026 · 7 min read
MCP tool poisoning and rug pulls, explained (and how to prevent them)
MCP tool poisoning hides instructions for the model inside a tool's description, and a rug pull swaps a harmless description for a hostile one after you approved the tool. Pinning tool definitions stops the silent swap, but the code behind a tool can change without its words changing, so each server also needs a sandbox that limits what it can touch.
01What is MCP tool poisoning?
Every tool an MCP server offers comes with a name, a description and a schema for its arguments. The client passes all of that to the model, and the model reads the description as guidance on when and how to call the tool. Invariant Labs named the attack in April 2025: a tool poisoning attack embeds malicious instructions in a tool description, text the model sees in full while the user usually sees a short summary or nothing at all.
Their proof of concept was an add tool whose description carried a hidden block telling the model, before adding two numbers, to read ~/.cursor/mcp.json and ~/.ssh/id_rsa and pass their contents in an extra sidenote argument, and to explain the call to the user with mathematics. In their Cursor test the agent did it, and the confirmation dialog did not show the full arguments. The user asked for a sum; the description alone turned that call into a file leak.
They also showed tool shadowing: a description from one server that changes how the model uses a different, trusted server's tool, for example telling it to send every email through a trusted send_email tool to an attacker's address. The poisoned server does not need to be the one that does the damage.
02What is an MCP rug pull?
A rug pull is tool poisoning with a delay. You install a server, read its tools, approve them, and later the server serves the same tool names with different descriptions. Invariant's write-up notes that a malicious server can change a tool description after the client has already approved it. Simon Willison's summary of the research adds the practical problem: some clients show tool descriptions when you first connect, but do not tell you when they change.
The protocol makes change normal. The MCP specification lets a server declare listChanged and send notifications/tools/list_changed, after which the client fetches the tool list again. That is useful for legitimate servers, and it means a list you reviewed once is not a list you can rely on. The specification also says clients must treat tool annotations, such as hints that a tool is read-only, as untrusted unless they come from trusted servers.
A rug pull does not even need the protocol. Many local servers start with a command such as npx -y some-package, which fetches whatever version is current at launch. A new release can change descriptions, add tools or change behaviour, and the next session picks it up.
03How to prevent tool poisoning: show, scan and pin
Invariant's recommended mitigations are three. Make tool descriptions clearly visible to users, so the text the model reads is text a person can read. Pin the server and its tools, using a hash or checksum of each tool description so a change is detected. And enforce boundaries and dataflow controls between servers, so one server cannot steer calls to another. The MCP specification adds client duties: show tool inputs to the user before calling the server, prompt for confirmation on sensitive operations, and log tool usage.
Pinning means recording a fingerprint of each tool definition when a person approves it, then refusing to pass a tool to the model if its fingerprint later differs. To be useful, the fingerprint should cover everything the model or the approval UI reads: name, title, description, input and output schemas, and annotations. A new tool that appears next to the approved ones deserves the same treatment as a changed one.
Scanning helps you review. Invariant's mcp-scan is now Snyk Agent Scan, Apache-2.0 licensed, which connects to configured MCP servers, fetches their tool descriptions and checks them for prompt injection, tool poisoning, tool shadowing and toxic flows. A scanner is a detector, so treat a clean result as evidence, not proof.
- Pin the package or image version, not a floating
latestornpx -y. - Pin each tool definition by hash and withhold any tool whose hash changed.
- Review the diff of a changed description before accepting it.
- Expose only the tools you need, by exact name.
- Show full tool arguments before sensitive calls, and log every call.
04Why pinning is not enough on its own
A pin protects words, not code. The description of list_issues can stay identical while the server process behind it is updated to read your home directory, open a connection to a new host or install something persistent. The model is not involved at all; the code simply runs. The MCP security best practices describe this as local MCP server compromise: a local server is a program running with the client's privileges, and a malicious payload inside it can execute any command those privileges allow.
First use is also taken on trust. If a server is hostile on the day you install it, a pin faithfully protects the hostile version. And a pinned, honest tool can still return results containing injected instructions, because a schema check confirms shape, not meaning.
So the specification's own guidance for local servers goes further than pinning: execute MCP server commands in a sandboxed environment with minimal default privileges, restrict file system and network access, and let users grant more access explicitly when needed.
05A layered setup: each server in its own sandbox behind one policy
Put the two defences together. A gateway between the client and the servers holds the pins and the policy: which tools are exposed, what changed, and who approved it. Behind it, each server runs in its own sandbox, with no access to your files or to the other servers, and a network allow-list naming only the hosts it needs. A server that needs no network gets none.
With that split, a rug pull in the description is withheld until a person reviews it, and a rug pull in the code is boxed in: it can reach the hosts on its list and nothing on your machine. Neither layer reads intent, so keep tokens narrowly scoped and keep a human in the loop for calls that change things.
Takeaways
- Tool poisoning hides instructions in an MCP tool's description, which the model reads in full and the user often does not see.
- A rug pull changes a tool's description or code after you approved it;
listChangedandnpx -ymake change routine. - Pin each tool definition by hash, withhold changed or new tools, and review the diff before accepting.
- Pins cover words, not code, and first use is trusted, so run each server in its own sandbox with a network allow-list.
- Scanners such as Snyk Agent Scan help review descriptions but are detectors, not boundaries.
Where kosa8 fits
kosa8 combines both layers in one gateway, kosa8 mcp serve. Third-party MCP servers each run in their own sandbox behind one policy, with the network rule you set when registering them. On first use the gateway records a SHA-256 fingerprint of each tool over its name, title, description, input and output schemas, and annotations. A changed or new tool is withheld until a person reviews kosa8 mcp pins diff and approves at a terminal, and an organisation can fix the pins in its signed policy. Every decision and call goes to the hash-chained audit log. The kosa8 docs list the limits: first use is trusted, results are checked for shape and not meaning, nothing scans content for injection, and the gateway itself runs as you.
Check yourself · +100 XP
You pinned every tool definition of an MCP server. What can a rug pull still change without being withheld?
A pin fingerprints the definition the model reads. An update to the server's code can change what a tool does while its name, description and schemas stay identical, which is why the server also needs a sandbox.
Questions people ask
What is the difference between MCP tool poisoning and a rug pull?
Tool poisoning is hostile instructions in a tool description. A rug pull is the timing: the description, or the code, turns hostile after you approved the tool.
Does mcp-scan prevent tool poisoning?
It detects it. Snyk Agent Scan, formerly mcp-scan, checks tool descriptions for prompt injection, poisoning and shadowing, which helps review, but it does not stop a server's code from doing something else at runtime.
How do I pin MCP tool descriptions?
Use a client or gateway that hashes each tool definition when you approve it and withholds the tool if the hash changes. Also pin the server's package or image version so updates are deliberate.
Sources
- MCP Security Notification: Tool Poisoning Attacks — Invariant Labs
- Model Context Protocol has prompt injection security problems — Simon Willison
- Tools — Model Context Protocol specification
- Security Best Practices — Model Context Protocol
- Snyk Agent Scan (formerly mcp-scan) — Snyk on GitHub
- Sandbox MCP servers — kosa8 guides
- AI agent network allow-list — kosa8 guides
Written by the kosa8 team. Every kosa8 command was checked against the CLI, and every claim about another product links to that product's own documentation. Spotted a mistake? Tell us.
Try it on your own machine
Give your next agent its own sealed machine.
One line installs kosa8 on your own machine. Every feature, plans from $29 a month.