Indirect Prompt Injection

The attack nobody types

Your input validation watches the chat box. The attacker never goes near it. They put the payload in a document, a ticket, a calendar invite, a web page, and wait for your application to read it on their behalf.

That is indirect prompt injection, and it is the version that scales.

The mechanism

An application decides what its model should read. A retrieval step pulls three documents. An agent fetches a URL. A support workflow loads the ticket body. All of that content lands in the same context window as your system prompt, and the model has no reliable way to mark one as trusted and the other as data.

Whoever controls any of that content controls part of your prompt. They do not need an account, a session, or a request to your API. They only need their text to end up somewhere your application will eventually look.

The essential asymmetry Direct injection requires the attacker to interact with your system. Indirect injection requires only that your system interact with theirs.

Where it enters

The question that matters is not whether your model is robust. It is which content reaches the context window without a person having read it first. In most production applications the answer is longer than the team expects.

Retrieval and RAG
Any indexed document. If users, customers, or an ingestion pipeline can add to the index, they can write into your prompts.
Browsing and fetch
An agent that reads a URL reads whatever is at that URL, including content served differently to automated clients.
Email and tickets
Inbound text from strangers, summarised or triaged automatically. The attacker is simply a customer.
File uploads
CVs, contracts, invoices, images with embedded text. Formatting can hide payloads from the human reviewer while leaving them fully legible to the model.
Third-party APIs
Any response you pass through to the model. You trust the vendor; you inherit whatever they were given.
Persistent memory
The nastiest case. A payload written into stored memory or notes executes again on every future session, long after the original input is forgotten.
Other models
Chained pipelines where one model's output is another's input. Injection propagates along the chain.

Why it is harder than the direct version

The payload does not have to look like an attack

It has to look like a plausible instruction to a system that cannot tell instructions from content. Polite, well-formatted, and phrased as a legitimate business rule reads as more credible to a model than anything resembling a classic jailbreak.

Detection has to happen somewhere with no context

A filter on user input never sees it. A filter on retrieved content has to judge arbitrary third-party text with no knowledge of what your application intends to do next. That is a much weaker position to defend from.

The blast radius is whatever the model can reach

Injection on its own produces text. It becomes an incident when the model has capability attached: a tool that sends email, a function that queries a database, an action taken with the user's authority rather than the model's. The severity of any injection finding is set by what happens next, not by the payload.

It persists

Direct injection lasts one conversation. A payload that reaches storage, an index, or a memory system stays until someone finds it, and nothing in a typical application is watching for it.

What actually reduces the risk

Nothing on this list eliminates the class. Each one shrinks what a successful injection is worth.

How we test for it

Testing starts from the data flow rather than from a payload list. Map every route by which content you did not author reaches the model. For each route, place a benign marker payload and check whether it survives to the context window. Where it does, escalate to what the model can be induced to do from there, including multi-turn and stored-payload cases.

Findings come back with reproduction steps and the capability chain attached, so severity is arguable rather than asserted. This sits alongside the direct-injection work described on prompt injection testing, and both are structured against a 31-pattern framework covering three categories of the OWASP LLM Top 10.


Common questions

Does a system prompt instructing the model to ignore injected instructions work?

It helps and it is not sufficient. The instruction competes with the injected one, and the outcome depends on phrasing, position, and model. It is a probabilistic mitigation being asked to do a deterministic job.

We only use retrieval over our own internal documents. Are we exposed?

It depends on who can write into that corpus. If any customer, contractor, or automated ingestion process can add a document, the corpus is not fully trusted regardless of where it is hosted.

Will a guardrail model catch indirect payloads?

Some of them. It is classifying arbitrary third-party text without knowing your application's intent, which is a harder problem than screening user input. Worth deploying, not worth relying on alone.

Is this theoretical?

No. Indirect injection is a recognised category in the OWASP Top 10 for LLM applications, and the conditions that produce it, untrusted content plus tool access, are present in most agentic deployments shipping today.

Find out what reaches your context window

The Tier 0 teardown is free. One LLM surface, mapped and tested by hand, findings written for engineers.

Book a call