Topic · Prompt Injection

Indirect Prompt Injection

Crawdad Security·Published ·Updated
In short

Indirect prompt injection is an attack in which malicious instructions are hidden inside content an AI agent reads — an email, a document, a web page, a tool response — rather than typed directly by a user. When the agent processes that content, its model may follow the embedded instructions, because a language model does not reliably distinguish instructions it was given from instructions contained in the data it processes. For an agent that can act, this turns any untrusted content into a potential command channel. It is the mechanism behind the most significant AI-agent security incidents to date, including EchoLeak.

Key facts

How is indirect prompt injection different from prompt injection?

Prompt injection is the general class: any attack where untrusted input causes a model to follow instructions it should not. Direct prompt injection is the version most people picture — a user types “ignore your previous instructions” into a chatbot. Indirect prompt injection is more dangerous for agents because the attacker never touches the agent. They plant the payload in content they know the agent will eventually read — an email in the inbox, a comment in a document, text on a web page the agent browses, a description in a tool the agent uses — and wait. When the agent processes that content in the course of normal work, the hidden instructions execute. The user did nothing wrong and often sees nothing happen.

How does indirect prompt injection work? (the EchoLeak example)

EchoLeak, disclosed by Aim Security in June 2025, is the clearest documented execution. An attacker sent an ordinary email to a Microsoft 365 Copilot user — no attachment, no link to click. The email sat in the mailbox. Later, the user asked Copilot an unrelated, routine question. To answer, Copilot assembled context, and the attacker's email was in scope. The hidden instructions in the email then executed: they directed Copilot to gather internal data the user could access (from OneDrive, SharePoint, and Teams) and encode it into the response as a reference-style Markdown image link pointing at an attacker-controlled server. When the response rendered, the image “loaded” — sending the embedded data out — through a Microsoft domain that was on the browser's content-security-policy allowlist. The user saw nothing. This is what researchers call an LLM scope violation: untrusted input commandeering the model to access and leak data the model is legitimately permitted to reach.

Why can't identity or permission controls stop it?

Because the attack never violates a permission. Throughout the EchoLeak chain, Copilot operated entirely within its granted access — it read data the user could read and made a request the browser's policy allowed. Every individual action was authorized. The attack lives in the composition of authorized actions: read privileged data, then emit it through an allowed channel. Permission models reason about individual accesses, not sequences of them, so no identity control was watching for the combination. This is the central lesson of indirect injection for agent security: least-privilege identity is necessary but cannot, by itself, stop an attack that stays within privileges.

How do you defend against indirect prompt injection?

The most useful defensive frame is the set of three conditions that must all hold for an indirect-injection exfiltration to succeed. The agent must ingest untrusted external content; it must have access to internal or sensitive data; and it must be able to communicate externally. Break any one and the attack fails. This matters because reliably distinguishing malicious from benign instructions inside ingested content is an unsolved problem — but you do not have to solve it if you can break one of the other two conditions. Of the three, the external communication (the egress) is the most cleanly enforceable in real time, because it is a discrete, observable event at a chokepoint rather than a property spread across everything the agent reads. A control that can inspect and block the outbound action — the exfiltration request — at the moment it is attempted is enforcing exactly where the attack chain is breakable. Content-level filtering of ingested text helps but is incomplete on its own, because payloads can be obfuscated to evade it.

How Crawdad approaches indirect prompt injection

Crawdad enforces at the point the three-conditions frame identifies as most tractable: the action, on the wire, including the egress. It inspects the concrete outbound actions an agent takes — a network request carrying data to an unfamiliar destination, a sensitive file being read — on the device where the agent runs, and can hold or block them before they complete. Because it acts on the action rather than trying to judge the language of the ingested content, an obfuscated injection payload and a plaintext one are handled the same way: both resolve to the same observable action. Crawdad's public benchmark includes a dedicated indirect-injection category covering payloads delivered through email, documents, RAG sources, tool output, and web content.

Reference pages for Prompt Injection (the general class) and the EchoLeak incident are being added to the Topics section.

Primary sources