Prompt injection examples and how to stop indirect attacks

How prompt injection and indirect prompt injection steer AI agents, four documented examples, and the layered controls that limit the damage.

Prompt injection is when text an AI agent reads changes what it does. The dangerous kind is indirect: the attacker never talks to the agent, but hides instructions in an email, a web page or a pull request that the agent reads later. You can't filter it out completely today. You can limit what an injected instruction can reach, check the agent's actions before they run, and test every channel the agent reads.

Most teams I talk to have tested their agent against someone typing "ignore previous instructions" into the chat. Fewer have tested what happens when that sentence sits inside a customer's email, a supplier's PDF or a GitHub issue.

This guide explains how direct and indirect prompt injection work, walks through four documented examples, and lists the controls that limit the damage.

Key takeaways

  • Indirect prompt injection is the bigger risk for agents. The instructions arrive in content the agent reads, not in the chat.
  • No single filter stops it. Language models do not separate instructions from data.
  • Limit the blast radius. Give the agent only the data, tools and exits its job needs.
  • Check actions, not only text. Decide whether each tool call is allowed before it runs.
  • Test every channel the agent reads, and retest when the agent changes.

What is prompt injection?

The OWASP Top 10 for LLM Applications lists prompt injection first. It defines it as input that alters a model's behavior or output in unintended ways.

A chatbot that is tricked into a rude answer is embarrassing. An agent is different. It reads your systems, calls tools with real credentials and acts on its own. When an agent follows an attacker's instructions, the result can be a leaked record, a changed account or a command run on a server.

The root cause is simple. A language model receives its instructions and the data it works on as one stream of text. It has no reliable way to tell "do this" from "here is a document that says do this." The UK National Cyber Security Centre makes this point in Prompt injection is not SQL injection. It says prompt injection "may never be totally mitigated in the way that SQL injection attacks can be."

Direct vs indirect prompt injection

Direct prompt injectionIndirect prompt injection
Who writes the instructionsThe person typing into the agentA third party who never talks to the agent
Where they hideThe chat messageAn email, web page, document, ticket, pull request, tool result or memory
Who sees themThe attackerOften nobody: text can sit in HTML comments, white text or metadata
Typical goalGet around the agent's rulesMake the agent act for the attacker, with the user's access
MITRE ATLASAML.T0051 LLM Prompt InjectionAML.T0051.001 LLM Prompt Injection: Indirect

Direct injection matters when the user is the attacker, for example a customer who wants a refund outside policy. Indirect injection matters for almost every agent, because almost every agent reads content that someone else wrote.

How does indirect prompt injection work?

Researchers described the attack in 2023. In Not what you've signed up for, Greshake and colleagues showed that an attacker can plant instructions in data an LLM application is likely to retrieve, with no direct access to the model.

The attack has four steps:

  1. Plant. The attacker puts instructions where the agent will read them: an email to your support inbox, a comment on a public issue, a review on a product page or a file in a shared drive.
  2. Retrieve. A user asks the agent to do its normal job. The agent pulls the planted content into its context, often through search or retrieval.
  3. Follow. The model treats the planted text as part of its task.
  4. Act or leak. The agent uses its own tools and access. It reads data, changes a record, runs a command or sends information out through a channel it is allowed to use.

The user often sees nothing unusual. The agent did what it was told. It was just told by the wrong person.

Simon Willison calls the dangerous combination the lethal trifecta: access to private data, exposure to untrusted content and the ability to communicate externally. An agent with all three can be turned into a data leak by one planted message.

Prompt injection examples

These four cases show the pattern. The researchers or vendors involved documented the first three. The fourth is a demo we run.

1. EchoLeak: one email, no clicks (Microsoft 365 Copilot, 2025)

Aim Labs found that an email with hidden instructions could make Microsoft 365 Copilot leak internal data. The victim did not need to click anything. When they later asked Copilot a related business question, Copilot pulled the email into its context and followed it. Microsoft tracked the flaw as CVE-2025-32711, rated it critical and fixed it on its servers in May 2025. Microsoft reported no evidence of exploitation. (BleepingComputer)

2. Comment and Control: coding agents leak their keys (GitHub, 2026)

In April 2026, researchers showed that text in GitHub pull requests and issues could steer three AI coding agents that run in GitHub Actions: Claude Code Security Review, Gemini CLI Action and GitHub Copilot Agent. The channels were a pull request title, issue comments and an HTML comment hidden in an issue body. The agents exposed API keys and GitHub tokens.

Copilot's agent encoded its environment in base64 and committed it to a file. That got past secret scanning, which looked for plaintext token formats. It also got past the network firewall, because GitHub was an allowed destination. The write-up records each vendor's response; Anthropic later changed the severity of its case to None. (Researchers' write-up, our analysis)

3. Semantic Kernel: from a prompt to code execution (Microsoft, 2026)

In May 2026, Microsoft disclosed two fixed flaws in its Semantic Kernel agent framework. In one, CVE-2026-26030, text that the model controlled ended up inside a Python expression that the framework evaluated. Microsoft reports that a crafted payload could get past the blocklist and run commands. The fix is in Python package version 1.39.4. Microsoft's conclusion: "AI models aren't security boundaries." (Microsoft Security Blog, our analysis)

4. A fake error page (our demo)

We show teams a simple attack. An agent is asked to read a web page. The page returns what looks like an error message, with steps to fix it. The steps tell the agent to print its environment variables and include them in its reply. The agent follows them and leaks environment variables and personal data. Nobody typed anything malicious into the chat.

In every case, the agent had untrusted input, access to something valuable and a way to send it out.

Why filters alone don't stop it

It is tempting to put a filter in front of the model and call it done. Filters help, but they cannot be the whole answer:

  • Attackers rephrase. A new wording, another language or an encoding can get past a pattern a classifier learned.
  • Hidden content is hard to see. In the Copilot case, the person who assigned the issue never saw the HTML comment.
  • Outputs can be disguised. Encoding a secret before writing it out beat secret scanning in the GitHub case.
  • Strict filters block real work. A filter that rejects every email that mentions "instructions" breaks a support agent.

The OWASP prompt injection prevention cheat sheet says the same. It treats input screening and structured prompts "as illustrative layers, not a complete prompt-injection defense." The NCSC goes further and tells buyers to beware of vendors that claim they can "stop" prompt injection. We agree, and that includes us.

How do you protect an AI agent from prompt injection?

Assume some injected text will get through. Then design the agent so that, when it does, it can't do much harm.

  1. Map the trifecta. For each agent, list the untrusted content it reads, the private data and tools it can reach, and every way it can send data out: replies, emails, comments, commits, links and file writes. Break at least one leg where you can.
  2. Give the agent least privilege. Scope tokens to one task and make them expire quickly. Don't give an agent that reads public content the same credentials as one that changes production. Research such as Design Patterns for Securing LLM Agents against Prompt Injections shows how to split an agent so the part that reads untrusted text can't call sensitive tools.
  3. Mark external content. Label retrieved content as data, keep it apart from the system instructions, and tell the model not to follow instructions inside it. This reduces the risk. It does not remove it.
  4. Check actions before they run. The text is not the risk. The action is. Check each tool call against what this agent is approved to do for this user. Then allow it, hold it for a person or deny it. OWASP recommends human approval for high-risk actions.
  5. Control the exits. Allow only the destinations the job needs, remove links and images from outputs where you can, and watch the channels you do allow, such as comments and commits.
  6. Use detection as one layer. A prompt injection classifier on inputs catches many known attacks at low cost. Measure it on your own traffic, including how often it blocks legitimate work.
  7. Log every decision. Record what the agent read, what it tried to do and what was allowed. Then you can investigate an incident and show reviewers what happened.

How do you stop a coding agent from leaking secrets?

Coding agents need their own section, because they often have all three legs of the trifecta. They read untrusted code and comments, they hold tokens, and they can push commits and post comments.

  • Keep long-lived secrets out of the agent's environment. Use short-lived tokens with the narrowest scope the task needs.
  • Treat outside contributions as untrusted. Pull request titles, issue bodies and comments from people outside your team are attacker-controlled input. Be careful with workflows that run an agent on them with secrets attached.
  • Limit write channels. If the agent only needs to suggest a change, don't let it push to branches or post public comments.
  • Don't rely on secret scanning alone. The GitHub case shows that an encoded secret can get through.
  • Run the agent in a sandbox with no access to the host's credentials, and check each command before it runs.

Do prompt injection detection tools work?

They work as part of a defense, not as all of it. When you evaluate one, ask:

  • What does it catch when the attack hides in documents, emails and tool output, not only in chat messages?
  • How often does it block legitimate work on your own traffic?
  • How much time does it add to each step?
  • Does it check the agent's tool calls, or only its text?

Test the answers on your agent, with your data. A public benchmark is useful context. It is not your workload.

How to test an agent for indirect prompt injection

Testing turns these ideas into evidence. Use an isolated copy of the agent with synthetic or masked data:

  1. List every channel the agent reads, including tool results and memory.
  2. Plant instructions in each channel, both visible and hidden.
  3. Give the agent its normal tasks. Record what it reads, which tools it calls and whether any data leaves.
  4. When an attack works, change a permission, a tool, the code or a runtime policy, and run the same attack again.
  5. Replay normal tasks to confirm the agent still does its job.
  6. Repeat when the agent's model, prompts, tools or permissions change.

Map each finding to ASI01 Agent goal hijack in the OWASP Top 10 for Agentic Applications and to MITRE ATLAS AML.T0051.001, so reviewers can place it. Our AI penetration testing guide covers the full test plan, and our MITRE ATLAS and NIST AI RMF mapping shows how to write the finding.

Questions

What is prompt injection?

Prompt injection is an attack where text changes what a language model does in a way its builders did not intend. In an AI agent, that can mean reading data it should not, calling a tool it should not, or sending information out.

What is the difference between direct and indirect prompt injection?

In direct prompt injection, the attacker types the instructions into the chat. In indirect prompt injection, the attacker hides instructions in content the agent reads later, such as an email, a web page, a document, a pull request or a tool's output. The person using the agent may never see them.

Can prompt injection be fully prevented?

Not today. Language models do not keep instructions and data apart, and the UK National Cyber Security Centre says prompt injection may never be totally mitigated the way SQL injection can. The practical goal is to limit what an injected instruction can reach and do.

Do prompt injection detection tools work?

They help as one layer. A classifier can catch many known attack patterns in inputs, but new wordings get through, and false positives can block legitimate work. Pair detection with least privilege and checks on the agent's actions.

How do I stop a coding agent from leaking secrets?

Keep long-lived secrets out of the agent's environment, give it short-lived tokens scoped to one task, treat pull request titles, issues and comments from outside contributors as untrusted, and limit the channels it can write to. Secret scanning alone is not enough, because an agent can encode a secret before it writes it out.

Keep reading

  1. AI penetration testing for agents in regulated industries

    What a penetration test of an AI agent should cover at a bank, insurer or hospital, how to run it safely, and the evidence that gets the agent approved.

    Daniel Begimher

    Testing
    6 min
  2. Armorer Guard: 3.4ms Inline Prompt Injection Defense

    Armorer Guard runs inline at agent boundaries where scanner latency becomes response latency. Latest benchmark: 3.4ms average local scans, 977 cases.

    Cristian Leo

    Research
    7 min
  3. Five days, five security incidents that broke the internet.

    PHP2Shell is broadly exploited, LiteLLM 1.107.0 shipped malware (49,000 downloads), and OpenCode, Railway and eMudhra put keys at risk. What to do now.

    Daniel Begimher

    Notes
    5 min

Stop collecting findings. Start closing them.