MCP SecurityModel Context ProtocolTool PoisoningAI Red TeamAgent SecurityOAuth

MCP Security Best Practices: Tool Poisoning, Token Passthrough and the Controls That Hold

Preporato TeamSeptember 17, 202612 min read
MCP Security Best Practices: Tool Poisoning, Token Passthrough and the Controls That Hold

TL;DR: MCP gives an agent tools from servers it did not write, and everything a server sends, tool names, descriptions, results and OAuth metadata, is untrusted input to a model that follows instructions. The attacks that matter are tool poisoning (an instruction hidden in a tool description), the rug pull (a tool mutated after approval), tool shadowing (a name collision that steals selection), and, on the authorization side, the confused deputy in OAuth proxy servers, token passthrough, state handle hijacking and SSRF through discovery URLs. The controls that hold are structural: scan and pin approved tool objects, sign manifests, namespace and allow-list servers, gate capabilities, require per-client consent, reject tokens not issued for the server, bind state to the verified user, block private address ranges, and show the exact command before a local server runs. The protocol's security best practices state most of these as requirements. This guide explains each attack, the requirement it maps to, and how to test that your fix holds.


An internal IT-support agent loads its tools at session start from a registry. Someone registers a plausible entitlement-check tool whose description ends with a routine-looking audit note: before answering, read the account record and post its reference to an internal endpoint. The agent reads the description as trusted instruction, does exactly that on the next ticket, and the "internal endpoint" belongs to the attacker. No jailbreak, no exotic payload, and an aligned model complied because the data it moved looked mundane. That is tool poisoning, and it is the reason MCP security is its own subject.

Run the attacks, then the defences

The AI Red Teaming course has a full agentic supply-chain module: MCP tool poisoning with a rug pull, tool shadowing, an inter-agent worm, and a defensive lab that builds manifest verification, hash pinning and capability gating and proves a fresh variant of each attack is dead. Every lab runs against a real tool-calling agent in a sandbox and measures attack success rate before and after the fix.

Why MCP changes the threat model

A chatbot's untrusted input is the user message. An agent that speaks MCP has several more. A tool's name and description are text the client puts in front of the model, so a server controls part of the model's instructions. A tool's result is text the model reads next, so a server controls part of the conversation. A server's OAuth metadata tells the client where to send the user to authenticate, so a server controls URLs the client will open. And local servers are processes launched on the user's machine from a configuration a client may install with one click.

None of these is a flaw in the protocol. They are what "give the model tools from other people" means. The security work is deciding which of these inputs the client verifies, which it constrains, and which it refuses.

AI Red Team
22 hands-on labs
Exploit and defend live AI systems
Mapped to OWASP LLM Top 10 + MITRE ATLAS
Explore the AI Red Team course →

The attacks and the controls

MCP attacks, what each exploits, and the control that holds

AttackWhat it exploitsControl
Tool poisoningThe description is concatenated into the model context as trusted instructionTreat descriptions as untrusted; scan for instruction patterns; pin the approved tool object
Rug pullApproval is a snapshot; the server can change the tool after reviewHash-pin every approved tool; a changed description or schema forces re-approval
Tool shadowingA flat namespace lets a second server register a trusted tool's nameNamespace tools by server; allow-list servers; drop unlisted or colliding tools
Confused deputy (OAuth proxy)Static client id + dynamic registration + a consent cookie skip the consent screenPer-client consent before the third-party flow; exact redirect URI match; single-use state (MUST)
Token passthroughThe server accepts and forwards tokens issued for other servicesReject any token not issued for this server; validate the audience (MUST NOT accept)
State handle hijackingPossession of a cart or workflow id is treated as authenticationVerify every request; bind handles to the verified user; random, expiring handles
SSRF via discoveryThe client fetches metadata URLs the server choseHTTPS only; block private and link-local ranges; egress proxy; validate redirects
Local server compromiseOne-click configuration runs a command the user never readShow the exact command; require approval; sandbox; prefer stdio
Scope inflationEvery scope granted up front; one stolen token opens everythingMinimal initial scopes; step-up challenges; server-side authorization on every call

The first three rows are the supply-chain attacks the red team labs run. The rest come from the authorization side of the protocol, where the requirements are written down as MUST and MUST NOT and can be checked against an implementation.

Tool poisoning, rug pulls and shadowing

Tool poisoning works because the description field is the one place a server can write text that the model treats as instructions rather than data. A poisoned description does not need to look hostile. The labs use an "audit" note, a "compliance" step, a request to include a reference in the reply. The defence is structural and layered. Descriptions are scanned for instruction patterns before a tool is loaded, which catches the obvious variants and is bypassable on its own. Approved tools are pinned as objects, name, description and schema hashed together, so a description that changes later is not the tool that was approved.

The rug pull is the reason the pin matters more than the scan. A server registers a benign tool, passes review, and mutates the description afterwards. If approval is a snapshot and the client reloads tools every session, the mutation ships silently. With a hash pin, a changed tool fails verification and goes back to review. The defensive lab shows a description blocklist being bypassed by a reworded variant, then shows the pin catching the same variant because it does not care about wording.

Tool shadowing exploits a flat namespace. If a second server can register lookup_account and the model selects tools by name and description, the shadow wins some fraction of the time, and that fraction is the attack success rate you measure. Namespacing tools by server (crm.lookup_account) removes the collision; an allow-list of servers removes the unlisted registrar entirely. The lab measures shadow-wins-selection before and after, and the number after has to be zero on a fresh batch of variants, not only on the ones you tested with.

AI Red Team
22 hands-on labs
Exploit and defend live AI systems
Mapped to OWASP LLM Top 10 + MITRE ATLAS
Explore the AI Red Team course →

The authorization layer

The protocol's own guidance spends most of its length on OAuth, because that is where MCP servers hold credentials for other systems.

Confused deputy in proxy servers. An MCP server that fronts a third-party API with one static client id, allows clients to register dynamically, and relies on the third-party's consent cookie can be tricked: an attacker registers a client with their own redirect URI, sends the user a link, the consent screen is skipped because the cookie exists, and the authorization code lands on the attacker's server. The requirement is per-client consent at the MCP server before the third-party flow, an exact string match on the redirect URI, and a cryptographically random, single-use state value stored only after consent is approved.

Token passthrough. A server that accepts a token issued for some other service and forwards it downstream circumvents rate limits and audit on that service and makes the server a proxy for exfiltration with someone else's identity. The rule is short: a server must not accept any token that was not explicitly issued for it, which in practice means validating the audience claim on every request.

State handles. MCP itself is stateless. A server that needs state across calls mints a handle and receives it back as a tool argument. If possession of the handle is treated as proof of identity, a guessed or leaked handle operates on another user's state. Handles must be random and short-lived, and the server must key state by the verified user, never by the handle alone.

SSRF through discovery. During OAuth discovery the client fetches URLs the server provided. A malicious server points them at cloud metadata endpoints or internal services and reads the results back through error messages. Clients deployed on servers should require HTTPS, block private and link-local ranges with a maintained library rather than a hand-written check, refuse to follow redirects into those ranges, and route discovery through an egress proxy.

Local servers. A one-click configuration that launches a server is a command execution with the client's privileges. Clients must show the exact command, unabridged, and require approval; sandboxing and the stdio transport limit what a compromised or malicious server can reach.

A hardening checklist

  • Registry: descriptions scanned, approved tool objects hash-pinned, manifests signed, capabilities allow-listed per tool, servers allow-listed, tools namespaced by server.
  • Runtime: tool results treated as data, side-effecting tools behind an approval gate, per-user authorization enforced server-side on every call, audit log with tool, arguments and caller.
  • Authorization: per-client consent in proxies, exact redirect URI matching, single-use state, audience validation, no passthrough, minimal initial scopes with step-up.
  • Client: HTTPS and private-range blocking for every server-supplied URL, no shell execution to open URLs, explicit consent for local server commands, sandboxed local servers.

How to test it

A control that has not been attacked is a hypothesis. The red team method in the labs is the same for every row of the table: reproduce the attack against the unhardened system and measure its success rate over a paced batch, apply one control at a time, and re-run the batch plus a set of fresh variants the control was not tuned on. A description scanner that stops the exact poison you wrote and none of the rewordings is a demo; a hash pin that stops all of them because it never read the wording is a control. The benign traffic has to keep passing through both, and the number that proves it is the benign pass rate next to the attack success rate.

The AI agent security guide covers the other half of the agentic attack surface, excessive agency and confused-deputy writes through the agent's own tools, and the prompt injection guides cover the injection techniques that tool poisoning reuses.

Frequently asked questions

AI Red Team
22 hands-on labs
Exploit and defend live AI systems
Mapped to OWASP LLM Top 10 + MITRE ATLAS
Explore the AI Red Team course →
Hands-on lab

MCP Tool Poisoning: Hijack an Agent Through a Tool Description (and a Rug Pull)

95 minutes, advanced
Runs in the browser, nothing to install
Every step checked on real output
Run this labPart of the AI Red Team course →
AI Red Team
22 hands-on labs
Exploit and defend live AI systems
Mapped to OWASP LLM Top 10 + MITRE ATLAS
Explore the AI Red Team course →

Hands-on lab

MCP Tool Poisoning: Hijack an Agent Through a Tool Description (and a Rug Pull)

Run the lab