Tool poisoning and prompt injection both end with a model following instructions its owner never wrote, but they arrive through different doors, are trusted by different people and last for very different lengths of time. Invariant Labs, who named tool poisoning in April 2025, described it as a form of indirect prompt injection, and that is true at the level of mechanism. For a defender the differences matter more than the family resemblance: one attack lives in content the agent reads during a single task, the other lives in tool metadata or code that the organisation approved and that is replayed into every session. This guide compares the two on trust source, persistence, failure modes and controls, so that platform owners, AI security architects and MCP server approvers can tell which control set they are actually missing. It does not repeat the injection technique catalogue in the Prompt Injection Guide or the hashing and drift procedure in MCP Tool Poisoning Detection.
Key takeaways
- The trust source is the real difference. Prompt injection rides on content nobody vouched for; tool poisoning rides on a tool somebody approved, so it inherits that approval and the scrutiny stops.
- Persistence changes the economics. MITRE ATLAS files LLM Prompt Injection (AML.T0051) under Execution and AI Agent Tool Poisoning (AML.T0110) under Persistence: one injection must be delivered again for each task, a poisoned tool keeps working in every session until it is removed.
- Controls split cleanly at the supply chain line. Pinning, definition hashing, source allowlists and change control address tool poisoning; content segregation, privilege drop after reading untrusted data and output validation address injection. Neither set covers the other.
- The overlap zone is tool output. A legitimate tool that returns attacker-written data is an injection channel, not a poisoned tool, and it defeats every tool-vetting control you own.
- Enforce outside the model for both. Deterministic permission checks, human approval with full parameters and egress limits are the controls that hold whichever door the instructions came through.
The short answer
Prompt injection is an attack on the data plane of an LLM application: an attacker places instructions in content the model will read while doing a task (a web page, an email, a ticket, a retrieved document or a tool result). OWASP LLM01:2025 describes indirect injection as occurring when an LLM accepts input from external sources such as websites or files. The instruction is present only while that content sits in the context window.
Tool poisoning is an attack on the control plane of an agent: the attacker controls part of a tool definition (name, description, input schema, annotations) or the tool's implementation, and the agent's host places that definition in the model's context every time it lists tools. The MCP specification describes tools as model-controlled, meaning the model discovers and invokes them based on the definitions it is shown. ATLAS defines AI Agent Tool Poisoning as achieving persistence by poisoning tools used by agents, including built-in tools and tools reached through MCP connections, to "maintain long-term influence over the agent's actions".
Side-by-side comparison
| Dimension | Prompt injection (per request) | Tool poisoning (persistent) |
|---|---|---|
| Where the instruction lives | Content processed during a task: user input, retrieved documents, emails, web pages, tool results | Tool metadata (description, inputSchema fields, annotations) or tool code and responses |
| Who must be trusted for it to land | Nobody: the content is untrusted by definition, the attacker only needs it to be read | The tool publisher and whoever approved the server; the attack inherits that approval |
| Delivery | Once per document, message or query that pulls the content in | Once per installation, then replayed by tools/list into every session |
| Persistence | Session-scoped; ATLAS notes effects "can persist throughout an interactive session" | Until the tool is removed or the definition reverted; ATLAS tactic Persistence (AML.TA0006) |
| Visibility to the user | Often hidden in content the user never reads closely | Hidden in metadata most clients do not display in full; Invariant called it "invisible to users but visible to AI models" |
| ATLAS IDs | AML.T0051, AML.T0051.000 Direct, AML.T0051.001 Indirect | AML.T0110 with AML.T0110.000 Definition and Instructions, AML.T0110.001 Implementation, AML.T0110.002 Runtime Response |
| Main control family | Content segregation, privilege drop, output validation, approval gates | Supply chain: source allowlists, pinning, full-definition hashing, change control, sandboxing |
Who is trusted: the trust source in each attack
Prompt injection: trusted reader, untrusted content
The attacker never has to pass a review. They write an email, publish a page, file a ticket or post an error event, and wait for an agent with useful privileges to read it. The NCSC describes the model as an "inherently confusable deputy" and gives the design principle that when an LLM processes information from a party, its privileges should drop to those of that party.
The EchoLeak case shows the pattern: a crafted email sat in a mailbox until an ordinary user question caused the assistant to retrieve it alongside internal data, and the hidden instructions turned an auto-fetched link into the exfiltration channel.
Tool poisoning: untrusted publisher, trusted tool
Here the attacker has to get a tool installed, or change one that already is. Once that happens the organisation's own approval becomes the attack's credential. Three patterns recur in the primary sources:
- Hidden instructions in the definition: Invariant's example was an innocuous "add" tool whose description told the model to read local configuration and SSH key files and pass them through an extra parameter, and not to mention it to the user.
- Rug pull: a server changes its tool definitions after the user approved them. The OWASP MCP Security Cheat Sheet warns not to assume a tool approved earlier is the same tool today.
- Shadowing: one server's description changes how the agent uses a different, trusted server's tool, without the poisoned tool ever being called.
The trust failure is upstream of the model: someone decided a publisher or package was safe and no one re-made that decision when it changed. The postmark-mcp case is the clearest example: fifteen clean versions earned trust, then version 1.0.16 added a single line to the send-email tool that blind-copied every message to an outside address, using the victim's own mail credentials. That was an implementation change (AML.T0110.001), not a description change, so it would have passed metadata review entirely.
Persistence: why a poisoned tool outlives the request
The MCP tools specification lets a server's tool list change over time. Servers that declared the listChanged capability SHOULD send notifications/tools/list_changed, and the client then calls tools/list again. Two consequences follow for defenders:
- Every session re-reads the definition. A poisoned description is not a one-off message; it is part of the agent's standing context whenever that server is connected. A single successful install therefore yields influence across every user, task and day until it is removed.
- Change is allowed and may be silent. The notification is a SHOULD and applies only to servers that declared the capability, so a client that relies on notifications to trigger re-review can miss a change. The MCP Security Best Practices page notes, in its session hijacking discussion, that list-change events could leave a client with tools it was not aware were enabled.
Prompt injection's persistence is shorter but not zero. The instruction lasts while the content stays in context, and it can become durable if the agent writes it somewhere it will read again: memory stores, shared notes, a ticket it updates, or a RAG index. ATLAS records that path separately as AI Agent Context Poisoning (AML.T0080) under Persistence. That boundary matters: once injected content is written to memory, the response looks more like tool poisoning (find and remove a stored artefact) than like injection (end the session). See Agent Memory Poisoning vs RAG Poisoning for that path.
| Question in an incident | Prompt injection | Tool poisoning |
|---|---|---|
| Does ending the session stop it? | Usually yes, unless it was written to memory or a shared store | No: the next session loads the same definition or code |
| What is the blast radius? | Sessions that retrieved the content | Every agent and user with the server connected, since the change |
| What has to be removed? | The planted content at its source, if reachable | The tool or server version, plus credentials it held |
| What has to be rotated? | Credentials the agent used in affected sessions | Every credential the tool could read or was given; removal from a registry does not remove installed copies |
Threat model for each attack
Prompt injection
- Attacker capability: write access to any content the agent may read. That includes write-only channels designed to be public, as the Sentry MCP agentjacking case showed: a public error-reporting key let outsiders plant an event that a legitimate MCP server later returned to a coding agent as a fix to run.
- Architecture in words: untrusted content enters context through retrieval or a tool call, the model plans, and the host executes with the agent's credentials.
- What makes it dangerous: private data access, exposure to untrusted content and an outbound channel in the same agent run.
- Failure modes: relying on a classifier or deny-list as the control (NCSC advises against deny-listing phrases because attackers can rephrase endlessly); letting the agent keep full privileges after reading external data; auto-rendering links and images; auto-approving shell commands suggested by tool output.
Tool poisoning
- Attacker capability: publish a server or package (including look-alikes of official ones), compromise a maintainer, or change a remote server they already operate.
- Architecture in words: an approved server's definitions enter context on every
tools/list, and its code runs with the credentials the server was given. - What makes it dangerous: inherited approval, persistence, reach across every connected agent, and access to the credentials configured for the server.
- Failure modes: reviewing only the
descriptionfield when OWASP says to treat the entire schema as an injection surface; hashing metadata but not pinning the package; approving once and accepting later versions automatically; trustingreadOnlyHintordestructiveHintannotations from a server that is not trusted, which the specification says clients MUST consider untrusted.
Where the line blurs
Three cases sit on the boundary, and classifying them correctly decides which team and which control owns them.
- Legitimate tool, attacker data: ATLAS separates AI Agent Tool Data Poisoning (AML.T0099), where an attacker plants content that a benign tool retrieves, from AML.T0110. The Sentry case belongs here. Tool vetting cannot catch it because the tool is honest; only output handling and action gating can.
- Poisoned tool, runtime response: AML.T0110.002 covers a tool whose responses themselves carry instructions. The bytes look like injection, but the source is a tool you approved, so removal and supplier action are the fix, not better filtering.
- Shadowing: the poisoned tool is never called, so tool-call logs show only the trusted tool being used with odd arguments. OWASP's multi-server guidance is to treat each server as an independent security domain and stop one server's descriptions from referencing another server's tools.
Distinct controls, and the shared ones
| Control | Stops or limits | Why it does not cover the other |
|---|---|---|
| Server source allowlist (official publisher, approved registry) | Tool poisoning via look-alike or unknown packages | Injection arrives through approved tools and ordinary content |
| Package and version pinning with reviewed upgrades | Implementation rug pulls such as postmark-mcp | Has no view of runtime content |
| Full-definition hashing (name, title, description, inputSchema, outputSchema, annotations) with re-approval on change | Definition poisoning and metadata rug pulls | OWASP notes it detects metadata changes, not code behind an unchanged definition, and nothing about data |
| Sandboxed server execution, per-server scoped credentials | Damage from malicious implementation | Injected agent still uses legitimate tools legitimately |
| Content segregation and labelling of untrusted data | Lowers injection success rate | A poisoned definition is presented as trusted tool metadata, not as data |
| Privilege drop after reading untrusted content | Limits what an injection can trigger | Poisoned tool influences planning before any untrusted content is read |
Output validation against outputSchema, results treated as untrusted | Injection through tool results, AML.T0110.002 responses | Does not see definitions or code |
| Shared: human approval showing full parameters | Both, for sensitive actions | Only as good as what the user is shown; Invariant's example relied on a simplified confirmation view |
| Shared: deterministic authorisation and egress limits outside the model | Both: caps what any steered agent can do | None: this is the backstop |
For the protocol-level controls in more depth, see the MCP Security Guide, and for pre-adoption review the MCP Server Trust Assessment.
Implementing controls in phases
- Inventory and classify (week 1 to 2): list every MCP server and tool reachable by agents, its source, version and the credentials it holds. Tag tools that return outsider-writable content (tickets, email, logs, web) as injection channels.
- Close the supply chain door (week 2 to 4): restrict installs to an allowlist of sources, pin package versions, and record a full-definition hash per tool per version. Start in alert-only mode for definition changes to measure noise, then move to quarantine (remove the tool from the agent's list until re-approved).
- Close the data door (week 3 to 6): label tool output and retrieved content as untrusted in context, validate structured results against
outputSchema, disable automatic rendering of links and images in agent responses, and drop to read-only or no-egress tools after an agent has read untrusted content in a run. - Gate actions (week 4 to 8): require human approval with full arguments for shell, package install, outbound messaging and financial or destructive operations. Pilot with one team, then tune by risk tier.
- Test both doors (ongoing): seed a poisoned definition and an injected document in pre-release tests; the first must be quarantined, the second must not trigger a gated action.
- Rollback: keep the last approved definition and package version for each tool so quarantine can revert rather than disable, and keep approval gates switchable per tool so an over-strict rule can be relaxed without removing the control everywhere.
Decision guidance: which risk dominates for you
- Agents with many third-party or community servers: tool poisoning is the larger exposure. Prioritise source allowlists, pinning and a gateway that enforces definition baselines. See MCP Gateway vs Direct MCP Connections.
- Agents with few, first-party tools that read external content: injection dominates. Spend on privilege drop, output handling and approval gates; vetting your own tools buys little.
- Coding agents on developer laptops: both are high; sandbox local servers and gate command execution.
- Small organisations: fewer servers, official publishers, manual pinning and approval for every write action; cheaper than drift detection.
- Large organisations: centralise through a gateway that records definition hashes, quarantines changes and logs tool calls to the SIEM, and assign tool approval to a named owner per server.
Worked scenarios
Scenario A, injection: a support agent with CRM read access, email send and a web-fetch tool summarises inbound tickets. A ticket contains hidden text asking the agent to email the top customer records to an outside address. With privilege drop in place, reading the ticket switches the run to a tool set without email send, so the instruction has nothing to call. Without it, the only remaining control is the approval prompt, and only if it shows the recipient and body in full. Response: end the session, neutralise the ticket and review that run's calls; no tool change is needed.
Scenario B, poisoning: the same agent uses a community "ticket formatter" server. An update changes its description to tell the model to add a fixed address to the CC field whenever the email tool is used (shadowing). Every later session is affected. The definition hash changes, the gateway quarantines the server, and the email tool's argument policy (recipients must be in the customer domain) blocks the CC even before quarantine. Response: remove or revert the server, search all sessions since the change for external recipients and rotate that server's credentials.
Detection and measurement
Log definitions and calls separately, because each attack leaves evidence in a different place. The MCP specification says clients SHOULD log tool usage for audit, and OWASP recommends logging every invocation with full parameters and user context to a SIEM.
- For poisoning: definition hash changes per server, new tools appearing mid-session, list-change events, package version changes, new outbound destinations from server processes.
- For injection: tool calls that follow retrieval of external content and were not requested by the user, failed or denied tool calls (NCSC notes these may show an attacker refining an attack), outbound links in responses, approval prompts declined by users.
Metrics that show the controls are working:
- Percentage of agent-reachable tools pinned to a reviewed version with a recorded full-definition hash (target 100%).
- Median time from a definition or version change to quarantine or re-approval.
- Percentage of tools returning outsider-writable content that run under privilege drop or approval gating.
- Number of sensitive tool calls executed without full-parameter approval (target zero).
- Seeded poisoning and injection test cases caught per release, as a percentage of cases run.
Framework mapping
| Framework | Prompt injection | Tool poisoning |
|---|---|---|
| MITRE ATLAS | AML.T0051 (Execution), AML.T0099 for content planted for tools to retrieve, AML.T0080 if written to memory | AML.T0110 and sub-techniques (Persistence, AML.TA0006) |
| OWASP | LLM01:2025 Prompt Injection | MCP Security Cheat Sheet section 2 (Tool Description and Schema Integrity), section 8 (Multi-Server Isolation), section 9 (Supply Chain Security) |
| NIST SP 800-53 Rev. 5 | SI-10 Information Input Validation, AC-6 Least Privilege, SI-4 System Monitoring | CM-2 Baseline Configuration, CM-3 Configuration Change Control, CM-7 Least Functionality, SR-3 Supply Chain Controls and Processes, SR-11 Component Authenticity |
| NIST CSF 2.0 | PR.AA-05 (least privilege permissions), DE.CM-09 (monitoring runtime environments) | ID.AM-02 (software and services inventory), PR.PS-01 (configuration management), GV.SC-07 (supplier risk over the relationship) |
| Both | AU-12 Audit Record Generation for tool calls and definitions | |
Common failure patterns
- Treating tool poisoning as just another injection: teams add a prompt classifier and assume tools are covered, while the poisoned definition is presented to the model as trusted metadata and the classifier never inspects it.
- Vetting tools and stopping there: a fully vetted, honest tool that returns tickets or error events is still an injection channel, as the Sentry case showed.
- Hashing descriptions, not code: metadata baselines miss implementation changes like postmark-mcp's one-line BCC; pair them with version pinning and egress monitoring.
- Approve once, trust forever: automatic upgrades and missing re-approval on definition change turn yesterday's review into today's blind spot.
- Incident response that only ends the session: wrong for poisoning, where the next session reloads the same tool.
Where identity fits
Both attacks spend the agent's credentials. Per-server, narrowly scoped, short-lived credentials limit a poisoned server to what it was given. See the Agent Identity and Access Guide and the AI Agent Authorisation Guide.
Practitioner checklist
- Classify every agent tool as a supply chain dependency and, separately, as a possible injection channel if it returns outsider-writable content.
- Restrict MCP server installs to an allowlist of official sources and pin versions.
- Hash the complete tool definition per version and quarantine on any change until re-approved.
- Treat annotations from untrusted servers as untrusted, as the MCP specification requires.
- Label tool results and retrieved content as untrusted and validate structured output against
outputSchema. - Drop the agent's tool set to read-only or no-egress after it reads untrusted content in a run.
- Require full-parameter human approval for shell, install, messaging, financial and destructive actions.
- Isolate servers from each other and issue per-server scoped credentials.
- Write separate response runbooks: end session and purge content for injection; remove tool, search all sessions and rotate credentials for poisoning.
Standards and references
- Model Context Protocol: Specification, Tools
- Model Context Protocol: Security Best Practices
- MITRE ATLAS: AML.T0110 AI Agent Tool Poisoning
- MITRE ATLAS: AML.T0051 LLM Prompt Injection
- OWASP GenAI Security Project: LLM01:2025 Prompt Injection
- OWASP Cheat Sheet Series: MCP Security Cheat Sheet
- NCSC: Prompt injection is not SQL injection (it may be worse)
- Invariant Labs: MCP Security Notification, Tool Poisoning Attacks
Related NHI Mgmt Group resources: Prompt Injection Guide · MCP Tool Poisoning Detection · AML.T0110 AI Agent Tool Poisoning · Agent Egress Control and Network Isolation Guide