Back to blog
Security
IntermediateForSecurity ArchitectsPlatform EngineersBackend Engineers
10 min

The Lethal Trifecta: A Practical Test for Prompt Injection Risk

Prompt injection cannot be filtered away. A practical 2026 guide to the lethal trifecta — private data, untrusted content, external communication — how to run it as an audit on your own agents, and which leg is realistic to cut.

prompt-injectionlethal-trifectaai-agent-securityllm-securitydata-exfiltrationmcp-securityowasp-llm-top-10
Contents

Every few weeks another vendor announces that they have solved prompt injection. A new classifier, a stronger system prompt, a guardrail model watching the output. And every few weeks a researcher publishes a bypass, usually within days, usually embarrassingly simple.

This is not incompetence. It is the shape of the problem. An LLM receives one stream of tokens and has no reliable way to tell which of them were instructions from you and which were data from somewhere else. The OWASP GenAI project states it plainly: given the way these models work, it is unclear whether fool-proof prevention exists at all. So the useful question is not “how do I block injections” but “what happens when one succeeds” — and there is a very good test for that.

The lethal trifecta: prompt injection becomes data theft when an AI agent has private data access, untrusted content exposure and external communication at the same time.

Why 99% Is a Failing Grade

The comparison everyone reaches for is SQL injection, and it is exactly the wrong one — not because the mechanism differs, but because the solution does not transfer.

SQL injection was solved. Parameterised queries create a real boundary: the query structure travels in one channel, the values in another, and the database never confuses them. The class of bug is closed by construction.

There is no parameterised query for an LLM. Your instructions, the retrieved document, the support ticket and the web page all arrive concatenated into the same context, and the model decides what to obey based on nothing more durable than tone and plausibility. Simon Willison, who was among those who independently coined the term “prompt injection” in the summer of 2022, has made the consequence a slogan worth memorising:

In application security, 99% is a failing grade.

A spam filter at 99% is excellent, because spammers are not adaptive in the moment. A prompt injection filter at 99% is a door that opens on the hundredth attempt, and the attacker has unlimited attempts and no deadline.

We have watched this play out. Microsoft ships classifiers for what it calls XPIA — cross/indirect prompt injection attack. The EchoLeak vulnerability in Microsoft 365 Copilot, tracked as CVE-2025-32711, got past them by the sophisticated technique of phrasing the malicious email as if it were addressed to a human, never mentioning AI or assistants at all.

The Lethal Trifecta

In June 2025, Willison named the pattern that turns an annoying injection into a breach. An LLM system is dangerous when it has all three of:

  1. Access to private data — your emails, your repositories, your customer records
  2. Exposure to untrusted content — anything an attacker can influence
  3. The ability to communicate externally — any channel that carries data back out

Three legs of the lethal trifecta: private data access, untrusted content exposure, and external communication. Any two are survivable; all three together allow an attacker to exfiltrate data through a prompt injection.

Any two of these are survivable. An agent with your private data and an outbound channel but no attacker-controlled input has nobody giving it malicious orders. An agent reading hostile web pages with no private data has nothing worth stealing. It is the third leg that closes the circuit.

If that shape feels familiar, it should. The Chromium security team has run on the Rule of 2 since 2019: never combine untrustworthy inputs, an unsafe implementation language, and high privilege — pick at most two. The trifecta is the same engineering instinct applied to agents, which is a point in its favour. This is not a novel framework invented for AI; it is a pattern that already survived a decade of browser security.

Run the Test on Your Own System

The value of the framing is that it converts to an audit. Three questions, in order.

What private data can this agent reach? Not what it is supposed to reach — what its credentials actually permit. The Supabase MCP incident is instructive: the agent operated with the service_role key, which bypasses row-level security entirely. The intended scope and the effective scope were different documents.

Where does untrusted content enter? This is the leg people consistently underestimate. Malicious instructions have arrived through Zendesk tickets converted into Jira issues, public GitHub issues, a PDF with white-on-white text, a web page using 1px font, code comments, and package documentation telling the agent to run an installer. If a stranger can influence any bytes the model reads, this leg is lit.

How could data get out? Also broader than it looks. Not just HTTP calls — a rendered Markdown image, a link the user might click, a reply posted to the public issue that started the attack, a database write, a search query sent to an attacker-controlled URL. In the Notion 3.0 report, the exfiltration channel was the agent’s own web search tool, because it accepted URLs as well as queries.

Three yeses means you have the trifecta. Not “you might be vulnerable” — you have the precondition, and the only remaining question is whether anyone has bothered.

One Integration Can Be All Three

The trap that catches teams is assuming the legs come from different places, so nobody owns the aggregate.

The GitHub MCP server exploit, published by Invariant Labs in May 2025, needed no combination at all. One official integration provided private repository access, exposure to attacker-authored public issues, and a publication channel through pull requests. A user asking their agent to “take a look at the issues” was enough to leak the names of their private repositories.

The same shape has since been demonstrated against the Supabase MCP and Atlassian’s remote MCP server — the latter neatly summarised by Cato’s researchers as “living off AI”. Atlassian’s own description gives it away: summarise work, create issues, perform multi-step actions. That is private data, untrusted input from public issues, and an outbound channel, in one product.

This is why per-tool authorisation matters more than per-server trust, and it is the practical case for the user-level permission controls I wrote about for MCP gateways: deny by default, allow-list individual tools, enforce at execution and not only at inference. If you are building servers rather than consuming them, the same boundary thinking applies from the MCP server guide.

Which Leg to Cut

You cannot remove private data access — that is usually the entire point of the agent. You cannot realistically eliminate untrusted content either; the list above shows how many doors that leg has, and Cursor’s response to the Jira exploit was essentially to ask users to only connect trusted sources, which is not a control.

That leaves external communication, and it is the right answer for a reason that has nothing to do with convenience: it is the only leg that can be enforced deterministically, outside the model, by code that cannot itself be talked into changing its mind.

OpenAI’s Lockdown Mode, now live, does exactly this — it limits outbound network requests to prevent the final stage of exfiltration. Their own documentation is refreshingly honest that it does not stop injections from occurring; it stops them from paying off.

The catch is that “restrict outbound” is much harder than it sounds, and the public record is a museum of allow-lists that failed:

Which Leg to Cut
System The allow-list How it broke
Microsoft 365 Copilot CSP image sources *.teams.microsoft.com hosted an open redirect
Salesforce AgentForce Trusted CSP domains An allowed domain had expired — researchers bought it
Google Antigravity Browser domain allow-list webhook.site was on the default list
Claude Cowork Outbound HTTP allow-list Anthropic’s own API domain was allowed; files uploaded there with the attacker’s key

Exfiltration allow-lists that failed in production: open redirects on trusted domains, expired domains still listed, logging services on default lists, and the vendor’s own API used as the channel.

Read that Claude Cowork row twice. The exfiltration channel was the vendor’s own API, on the allow-list for obvious reasons, used with an attacker-supplied key. Any domain that accepts a write and lets someone else read it later is an exfiltration vector, and that category is much larger than a threat model usually admits.

The 2026 Counter-Argument

In August 2026, Anthropic made auto mode the default in Claude Code and published numbers worth taking seriously. A third-party evaluation by Trajectory Labs ran 72 held-out indirect prompt injection scenarios; none of 720 attack attempts succeeded against their models in auto mode. In the same body of work, a study of 1,053 paid testers swapped one permission prompt for a clearly dangerous command: only 13.6% of humans refused it, while auto mode would have blocked 89%.

Both halves deserve honesty. The second is the more uncomfortable one — it is strong evidence that click-to-approve is not a real control. Confirmation fatigue is not a character flaw, it is the predictable result of asking a person to adjudicate every few seconds.

But 720 held-out scenarios is a measurement against known attack shapes, not a proof that the class is closed. Willison — who is on record predicting a serious coding-agent security incident in 2026 — has asked for independent confirmation and offered an attack he does not think auto mode addresses: a malicious package whose documentation tells the agent to fetch and run something else during a legitimate-looking test setup.

The reasonable position is that these mitigations raise the cost of attack substantially and change nothing about the architecture you should build. A lower probability of a successful injection is worth having. It is not a reason to hand an agent your production credentials.

What to Actually Do

Prompt injection defence checklist: cut the exfiltration leg, scope credentials to non-production, allow-list individual tools, require human approval for side effects, and design for survivable compromise.

Cut the outbound leg where you can. Deterministic, code-enforced, not adjudicated by a model. Deny by default and audit the allow-list for open redirects, expired registrations and anything that stores data others can read.

Scope credentials so theft is boring. The single most effective control for coding agents: any key an agent can see belongs to a non-production account with hard spending limits. If it leaks, you rotate it and move on.

Allow-list tools, not servers. One integration can carry all three legs. Grant individual capabilities, and re-run the trifecta test each time you add one — the risk is in the combination, not in any single addition.

Require human approval for side effects, not for everything. The 13.6% number is what happens when you ask people to approve constantly. Reserve the interrupt for actions that leave the system: sending, posting, writing, publishing.

Treat untrusted content as data. Segregate and mark external content rather than concatenating it into the instruction stream, per the OWASP LLM01 guidance. This does not solve the problem — nothing at the prompt layer does — but it makes the boundary explicit for the humans reading the code.

Test adversarially. OWASP’s recommendation is to treat the model as an untrusted user and pen-test the trust boundary. Assume the injection lands; verify the blast radius.

The Bottom Line

Prompt injection is now four years old as a named problem. It is LLM01 in the OWASP Top 10 for LLM Applications, catalogued in MITRE ATLAS, and still shipping in flagship products from Microsoft, Google, Atlassian, Salesforce, Notion and Anthropic — companies with serious security organisations. That track record should end any expectation that your classifier will be the one that holds.

The lethal trifecta is valuable precisely because it stops asking that question. It does not try to make the model trustworthy. It asks what the model is permitted to do when it is inevitably fooled, and gives you three concrete things to look at in an architecture you already have.

Run the test on whatever agent you shipped last quarter. Private data, untrusted content, external communication. If you can say yes to all three, you do not have a hypothetical risk — you have a working exploit chain waiting for someone to care enough to use it.

Frequently asked questions

What is the lethal trifecta in AI security?

It is the combination of three capabilities in one LLM system: access to private data, exposure to untrusted content, and the ability to communicate externally. Simon Willison named it in June 2025. Any two of the three are manageable; all three together mean an attacker who plants instructions in the untrusted content can make the agent read your private data and send it out. The framing matters because it turns a vague fear into a checklist you can apply to a real architecture in minutes.

Can prompt injection be fixed with filtering or a guardrail model?

Not reliably. A filter reduces the probability of a successful attack, but an adversary retries indefinitely, and as Simon Willison puts it, in application security 99% is a failing grade. The OWASP GenAI project is equally direct: given how models work, it is unclear whether fool-proof prevention exists at all. Filters are worth deploying as one layer, but treating them as the control is how systems get breached.

Which leg of the trifecta should I cut?

Usually external communication, because it is the least useful capability to most applications and the only one that can be enforced deterministically outside the model. Cutting access to private data cripples the agent, and cutting exposure to untrusted content is nearly impossible in practice — malicious instructions arrive through support tickets, issues, PDFs, web pages, code comments and package documentation. Restricting outbound traffic is the leg you can actually hold.

Why is MCP particularly risky for prompt injection?

Because a single MCP server can supply all three legs at once, and users combine servers without thinking about the aggregate. The GitHub MCP server exploit in May 2025 showed one integration providing private repository access, exposure to attacker-authored public issues, and a way to publish stolen data through a pull request. Supabase and Atlassian MCP servers have been shown to have the same shape. The fix is tool-level allow-listing and treating each added server as an expansion of the trust boundary.

Is prompt injection in resumes a real thing?

Yes, and it is documented in the OWASP Top 10 for LLM Applications. Scenario six describes an attacker uploading a resume containing split malicious prompts that manipulate an LLM screening it into a positive recommendation. Kai Greshake's Inject My PDF work is cited as a reference. There is also an unintentional variant in the same list: a company hides an instruction in a job description to catch AI-written applications, and an applicant using an LLM trips it without knowing.

Did Anthropic solve prompt injection with auto mode?

They published strong numbers in August 2026 — a third-party evaluation by Trajectory Labs where none of 720 attack attempts across 72 indirect injection scenarios succeeded against their models in auto mode. That is a real result and better than human review, which caught only 13.6% of harmful actions in the same study. But it is a mitigation measured against known scenarios, not a proof that the class is closed, and Willison has publicly asked for independent confirmation. Treat it as raising the cost of attack, not as removing the need for architecture.

From the community

Discussion on the Fediverse

Replies from Mastodon and Bluesky — straight from the open web, no tracking.

Loading replies …

ENDE