Security · Explainer
What prompt injection is
On this page
The short answer
Prompt injection is text that reaches a model and changes what it does, whether or not you put it there. It works because instructions and content arrive through the same channel: the model reads everything in the request as one stream, and cannot reliably tell your rules from a sentence inside a document you asked it to summarise. OWASP lists it as LLM01, the first entry in its top ten for AI applications, and says no fool-proof prevention is known.
The interesting question is not how to stop it. It’s what your system lets it do.
Why it works
A model does not have two inboxes. Everything you send, the system instructions, the conversation, the fetched web page, the tool result, arrives as one sequence of text, and the model works out what to do from all of it together. That is what makes it useful with arbitrary content, and it is exactly what makes injection possible.
OWASP’s definition is deliberately broad: any input that changes the model’s behaviour or output in a way you did not intend. Nothing about it requires a person to be able to see the text. If the model reads it, it counts. White text on a white background counts. So does a comment in a file, and metadata nobody displays.
Jailbreaking is the term it gets confused with. OWASP treats it as a subtype: injection is changing behaviour through inputs, and jailbreaking is the narrower case of pushing the model to abandon its safety rules altogether.
Direct and indirect injection
| Where it comes from | Who has to be malicious | |
|---|---|---|
| Direct | The person using the system, typing into it | The user |
| Indirect | Content the model reads: a web page, a document, an email, a ticket, a tool result | Anyone who can put text where your system will read it |
Indirect is the serious one. It happens whenever the model takes in something from outside, a website or a file or a message, and that content changes what it goes on to do.
Consider what that means for anything agentic. Summarise this page, read this inbox, triage these tickets, review this pull request. Every one of those is an instruction to go and read text that somebody else wrote. Your user does not need to be an attacker. The attacker only needs to have written something your system will eventually look at.
OWASP’s own worked example is deliberately mundane. Somebody asks an assistant to summarise a web page. The page carries hidden instructions telling the model to include an image, and the address that image is fetched from has the private conversation attached to it. Asking for the picture is what sends the data out.
Why tools change the severity
Injection against a model that can only talk produces a wrong or embarrassing answer. Injection against a model that can act produces an action.
OWASP ties severity directly to capability. What an injection is worth depends on the business the model sits in and on how much freedom it was given, and the range runs from leaking sensitive information, through reaching whatever functions the model is allowed to call, to running commands in the systems it connects to.
The sharpest way to think about which systems are exposed comes from the independent researcher Simon Willison, whose lethal trifecta names three capabilities that are dangerous specifically in combination: access to private data, exposure to untrusted content, and a way to send data back out. Any two are usually fine. All three, and a successful injection has a route in, something worth taking, and a way out.
Most useful agents are built to have all three, because that is what makes them useful. Which is the actual problem.
There is a supply-chain version of this too. A model chooses tools from their written descriptions, and the MCP specification is explicit that a tool’s description should be treated as untrusted unless it came from a server you trust. A tool description from somebody else’s server is an instruction channel into your agent’s decision-making.
The Microsoft 365 Copilot case
In June 2025 Microsoft published CVE-2025-32711 against Microsoft 365 Copilot, described in the record as command injection that “allows an unauthorized attacker to disclose information over a network”. The two published severity scores disagree. Microsoft rated it 9.3, critical. The National Vulnerability Database rated the same entry 7.5, high.
The attack was one email. It carried instructions written for the model and hidden from the person, and the target never had to open it. When the user later asked Copilot an ordinary question, the retrieval step pulled that email into the model’s context along with everything else it judged relevant, and the instructions inside it ran as part of the request.
A published case study of the exploit records how the defences failed. It got past Microsoft’s own cross-prompt-injection classifier, then past link redaction, by chaining product behaviour that was working as designed: reference-style links, images fetched automatically when a message renders, and a proxy the content security policy already permitted. A classifier built for this exact attack class was in the path, and the attack went through it.
All three capabilities are present. The private data is the tenant. The untrusted content is any inbound email. The way out is any resource the rendered answer is allowed to fetch. Microsoft says the fix was applied on its side, that customers had nothing to do, and that it saw no exploitation in the wild.
What helps
Every one of these limits what a successful attack can do. None of them stop the attack, and OWASP is direct about why: “Given the stochastic influence at the heart of the way models work, it is unclear if there are fool-proof methods of prevention.”
Retrieval and fine-tuning are the two that get assumed to fix this. OWASP addresses it directly: both make answers more relevant and more accurate, and neither closes the vulnerability.
Nor does asking nicely. An instruction in your system prompt telling the model to ignore instructions in documents helps, and models often obey it. It is not a control, because the attacker’s text reaches the model the same way your instruction does, and the model has no reliable way to tell them apart.
Common questions
Is prompt injection the same as jailbreaking?+
Can it be fixed?+
Do I need to worry if my app is just a chatbot?+
Where does the malicious text usually come from?+
Is a system prompt telling it to ignore injections enough?+
What is the single most valuable thing to do?+
Keep learning