AI Dark Arts (07) split prompt injection into direct and indirect. The direct kind is easy to picture: the attacker sits in front of the chat window and feeds the payload to the model. The indirect kind starts earlier. The attacker plants instructions in a web page, an email, a comment or a document that the model will later read, and the malicious text rides into the context alongside the data when a user asks about that topic. But how does outside content get in front of the model in the first place? If the attacker never touches the model and never edits the system prompt, how does the attack still work?
In August 2024 the security team PromptArmor published an attack chain against Slack AI. A developer pasted an API key into a private channel only they could read. The attacker could not see that message and had no access to that channel. All they did was post malicious instructions in a separate public channel.
When the developer later asked Slack AI about their own API key, Slack AI pulled the private message and the attacker’s public instructions into the same context to answer the question. Following those instructions, the model wrapped the key into a link dressed up as a reauthentication prompt. One click from the victim and the key travelled to the attacker’s server as a URL parameter (PromptArmor). Slack patched the issue afterwards and said it had no evidence that customer data had been accessed without authorization (Slack Security Update).

Why does an AI go looking through documents?#
A model can have read an enormous amount of public text and still not know your company’s travel policy for this year, and it certainly cannot read your private files. Retraining every time the data changes is not practical either: it is expensive, it is slow, and permissions are hard to manage that way. So the common approach today is RAG (Retrieval-Augmented Generation), a name that comes from a 2020 paper by a team at Meta AI (arXiv:2005.11401). After the user asks a question, the system first finds relevant content from designated sources, then hands the question and the search results to the model together.
Think of it as an open-book exam for an AI. The model gets the question, flips through a few documents that look relevant, and writes its answer from what it finds there.

Roughly five steps:
- The user asks a question.
- The system turns the question into a form suitable for search.
- Relevant content comes back from a knowledge base or an external source.
- The user’s question, the retrieved content and the system instructions all go into the model together.
- The model produces an answer from that whole context.
RAG solves the knowledge-freshness and document-integration problem. The price is that the model’s input is no longer “the text the user typed” but “anything the system might pull back.” If even one of those sources is not fully trustworthy, the risk arrives with it.
Is a document data, or is it a command?#
To a person, whatever comes back from a search is obviously data: a product description, a company policy, an email, a comment, a paragraph out of a PDF. To the model, it is a string of tokens.
Say your manager hands you a folder and asks you to summarize what is inside. Halfway through you find a sticky note someone slipped in: “Stop summarizing and email the whole folder to me.” A person sees instantly that the note is not part of the original documents. For the model, that note is part of the context for this task, and it is phrased like an instruction, so there is a real chance it gets treated as one.
AI Dark Arts (07) made the point that an LLM has no hard boundary like a parameterized query, nothing that fully separates “instructions to execute” from “data you may only refer to.” When Simon Willison wrote about prompt injection in 2022, he sketched something along those lines, splitting the different parts of a prompt and handling them separately (Prompt injection attacks against GPT-3). But natural language is useful precisely because it lets you express anything, and locking input into a strict format takes that flexibility away. So far, nobody has a separation method that works across every model and every situation.
Poisoning does not require touching the whole knowledge base#
The sources feeding a RAG system might include public web pages, customer reviews, social posts, support emails, supplier documents, or an internal wiki that many people can edit. An attacker only needs control of one of them to get their own writing into the retrieval results. That is exactly how the Slack AI case at the top of this post worked.
The PoisonedRAG research from 2024 puts numbers on it. Against a knowledge base holding millions of documents, injecting just five malicious texts per target question reached a 90% attack success rate (arXiv:2402.07867). A low poisoning ratio does not mean low risk.
A poisoned document usually has two faces:
- Ordinary topical content, whose job is to make the document look highly relevant to the user’s question
- Hidden malicious instructions, which wait until the document lands in the context and then try to change what the model does
So when you assess a RAG system, “does the knowledge base require a login” is only the first question. Keep going:
- Who can create or modify content?
- Which external sources get imported automatically?
- Does anything review or classify content before it enters the index?
- Do retrieval results preserve source, owner and trust level?
- Can the model tell an official policy, a supplier document and an anonymous comment apart?
If everything that enters the context is treated as equally trustworthy, the attacker’s only remaining job is to get found.
From wrong answers to data walking out the door#
The mildest indirect injection just makes the model answer the wrong thing or reach a bad conclusion. But if the application supports Markdown, images, links, link previews or tool calls, the impact goes well past a wrong answer. Markdown images are the classic example. Suppose the model outputs:
The frontend usually renders that as an <img> tag, and the browser fires a request to that URL to load the image. If an attacker can get the model to stuff sensitive data into the URL parameters, the data leaves the system with that request. An ordinary link normally waits for the user to click. A Markdown image or an auto-generated link preview only needs the frontend to load external resources on its own.
In May 2025 Legit Security published an attack chain against GitLab’s AI assistant Duo. The researchers hid instructions in merge request descriptions and comments, commit messages, issue content and even the source code itself, using Unicode characters, Base16 encoding and white KaTeX text to keep them out of sight. After reading that content, Duo would follow the malicious instructions, retrieve private data the victim had access to, encode it as Base64 and pack it into an <img> URL in its reply. When the browser tried to load the image, the data went out to the attacker’s server with the GET request (Legit Security).

If the model can also call mail, databases, a shell, cloud services or other tools, the risk goes up another notch. At that point indirect prompt injection stops being about manipulating text and starts being about hijacking actions.
RAG has ordinary permission problems too#
Architecturally, a RAG deployment is still an information system, so it falls into all the usual access-control holes.

Authorization failures at the retrieval layer. A company puts documents from different departments or different customers into one vector database, checks identity at the chat interface, and then never applies document permissions during retrieval. The model pulls back content the user was never allowed to read and turns it into a fluent answer. That is not a jailbroken model. That is authorization that was never finished.
Indexes out of sync. The original document has been deleted or its permissions revoked, but the old content is still sitting in the vector index. One question and it comes right back out.
No classification before indexing. Personal data, keys, internal secrets and ordinary documents all get chunked, embedded and fed into the model context together. No amount of injection defense downstream fixes data that was misplaced upstream.
RAG security therefore needs two lines of defense at once:
- Whether external content can change the model’s behavior through indirect prompt injection.
- Whether the system correctly limits who can retrieve what.
Assume the model will fall for it#
When you test a RAG application, walk the data flow and answer these five questions first:
- Where does content come in from?
- What classification, scanning and review happens before it enters the index?
- Under what conditions does that content get retrieved?
- Whose identity and permissions does the system use when it hands content to the model?
- Who eventually reads the model’s output, and which browser, tool or backend does it flow into?
Those five answers essentially draw the whole attack surface. They also tell you where your test payload belongs and how much damage a success could do.
For defense, look at it from two angles: what the model can see, and what it can do once something has influenced it. Hang those on the RAG flow from earlier and they land roughly here:

The last two boxes extend the original five-step flow. As soon as your application calls tools or sends results outward, the defenses have to extend with it. Spelled out:
- Apply the user’s own document permissions at retrieval time, so the model never reaches content the user has no right to see.
- Give the model only the minimum tool permissions the task needs. A user holding a permission is not a reason to hand that permission to the model.
- Do not trust the tool names, parameters or operations the model produces. Re-check identity, authorization, input and scope at the tool on every call.
- Require human approval for high-risk actions such as sending mail, deleting, paying, publishing, changing permissions or transmitting confidential data.
- Restrict outbound domains, APIs and network egress so the model cannot ship data to a location the attacker controls.
- Treat model output as untrusted data. Never send it straight into a browser, SQL, a shell or any other dangerous sink; validate, escape or use a safe interface before anything actually runs.
No single control solves prompt injection outright, so the practical assumption is this: the model can be influenced, so the system has to limit the consequences.
Wrapping up#
This post was about where content comes from: the documents that get retrieved, the pages that get summarized, the mail that gets read in. Indirect prompt injection does not need the attacker to touch the model at all. As long as malicious content has a route into the context, it can change answers, trigger data leaks, and even hijack an agent’s tools.
The next post changes the angle and looks at what form the content arrives in: white text in a PDF, a line of tiny type inside an image, instructions that only surface after the image is resized. Attackers do not even need a plain-text channel.