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.
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.
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.
- Constrain capability. Ask what the model is permitted to do without a human in the loop, then remove everything that does not need to be there. This is the only control with a hard ceiling on damage.
- Separate authority from the model. Actions with consequences should run under permissions checked against the user, not inherited by whatever the model decided to call.
- Mark untrusted content as untrusted. Structural separation between instructions and retrieved data is imperfect, and still better than concatenation.
- Treat model output as untrusted input. Anything downstream that renders, executes, or parses it needs the same handling you would give a form field from the internet.
- Confirm at the consequence. Human authorisation on the small number of actions that actually matter, rather than on everything.
- Log the context, not only the conversation. If an incident happens, you need to know which retrieved document was in the window.
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.