Indirect injection arrives through whatever the agent reads on your behalf: a web page, a PDF, a ticket, an email, a calendar invite, a tool's own output. Protecting an agent from it means two things at once. Reduce what gets in, per channel, knowing that none of those controls is airtight. Then reduce what the agent can do with what got in, which is the part that holds when the first part fails. MITRE ATLAS files the attack as AML.T0051.001, and the persistent variants as AML.T0080 Context Poisoning and AML.T0081 Modify AI Agent Configuration.
Email and messages the agent summarises
The realistic control. Strip active content and hidden markup before the text reaches the model: white-on-white spans, zero-width characters, HTML comments, alt text, metadata. Summarise from plain text. Do not let the summariser hold a send tool in the same session.
The limit. Hidden text is the lazy version of the attack. An instruction written in ordinary visible prose, addressed to the assistant, survives every sanitiser, because there is nothing malformed about it.
Tickets, issues and records in a system of record
The realistic control. Treat every field a customer or an outside user can write as untrusted input, and scope the agent's reach to the one record it was given. One ticket per session, one repository per session, and no credential that spans the tenant.
The limit. The agent still needs to read the record and still needs to write somewhere. Writing attacker-readable text into a field the reporter can see is exfiltration that never touches the network.
Web pages and documents fetched during a task
The realistic control. Fetch through an allowlist where the task allows it. Render to text, drop scripts and hidden nodes, and mark the whole span as retrieved content so the model can weight it below your instruction.
The limit. Marking is advisory, not a boundary. And an allowlist is only as trustworthy as the least careful page on it, including pages that accept comments.
Files and attachments
The realistic control. Extract text in a sandbox with no network, cap size and page count, and normalise invisible characters. Keep extraction and action in separate processes with separate credentials.
The limit. The payload can be the document's legitimate content. An invoice that says to pay a new account is indistinguishable, as text, from an invoice that says to pay the old one.
Tool descriptions, MCP servers and configuration
The realistic control. Pin the tool set at deploy time and review it like code. A tool description is a prompt: it is read by the model every turn, and a change to it changes the agent's instructions. Require a signed, reviewed change to add a server or edit a description, and refuse configuration written by the agent itself.
The limit. This is the fastest-growing channel and the one with the longest persistence. ATLAS gives it its own technique, AML.T0081, because a poisoned configuration does not need the attacker present when the action runs.
Memory and earlier turns
The realistic control. Decide what is allowed to persist. Summaries written by the agent are attacker-influenced if the source was. Expire memory, scope it per task, and never let a stored note carry an instruction forward.
The limit. The same text, once it is in memory, no longer looks retrieved. ATLAS separates memory and thread poisoning as sub-techniques of AML.T0080 precisely because the provenance is gone by then.
The controls that hold across every channel
Per-channel hygiene raises the cost. These four change what an injection can achieve, whichever channel it used.
- Cut a leg of the trifecta. Private data, untrusted content, external communication: with any one removed, the exfiltration path closes (Willison). Meta's Rule of Two is the same constraint as a build rule, and it says plainly that combining all three requires a person in the decision (Meta).
- Separate reading from acting. The model that handles untrusted content holds no tools; the model that holds tools never sees raw untrusted text (Willison, 2023).
- Remove the standing credential. OWASP LLM06 names excessive permissions as a root cause, and the mitigation is removal rather than monitoring (OWASP).
- Require a signature on what cannot be undone. The only control whose effect does not depend on having recognised the attack first.
The read is not the risk. The action is. Every channel above is a channel your agent is supposed to read, which is why hardening the channels alone never finishes the job.
Related: indirect prompt injection, defences and their limits, and containing a successful injection.
The instruction got through anyway. Now what?
Now the action meets a policy it cannot talk its way past, which is the layer ZIFFER is.
The agent holds no credential on your systems. It proposes an action, and the credential that performs it sits with an executor on your side of the line. The proposal from a compromised agent is graded against the same signed policy as a clean one, because the risk, the reversibility and the owner of the target are recomputed from your policy rather than read from the proposal. Irreversible actions are held for a quorum of two named humans who sign the exact bytes that will run, and a hold nobody signs expires with nothing run. Every outcome, refusals included, leaves a signed receipt naming the action, the policy version, the signers and the time.
ZIFFER is not a guardrail. It sanitises nothing, detects no injection and prevents none. It decides whether a proposed action is entitled to run. See agent authorization, the agent audit trail and every refusal.