The lethal trifecta
Use Simon Willison's three-capability model to decide whether a given agent configuration is exploitable at all.
In June 2025 Simon Willison named the combination that turns prompt injection from an annoyance into a breach. He called it the lethal trifecta, and it is the most useful single test for whether an agent design is dangerous.
- Access to private data: the agent can read something worth stealing.
- Exposure to untrusted content: the agent processes input an attacker can influence.
- An ability to communicate externally: the agent can get data out.
Any two of these is usually survivable. All three together means a single piece of poisoned content can exfiltrate your data, with no vulnerability in any of your code.
Work through it. The agent reads a support ticket containing hidden instructions; that is untrusted content. It has vault access to answer questions about the customer; that is private data. It can fetch a URL to check a status page; that is the exfiltration channel. Nothing is broken. Every capability was deliberately granted and individually reasonable.
The exfiltration channel is the one people consistently underestimate. It does not need to look like a network call:
- Rendering a markdown image whose URL encodes the data.
- Generating a clickable link the user is nudged into following.
- Writing to a shared document, ticket, or repository the attacker can read.
- Making any outbound request at all, including a DNS lookup.
The practical method: audit every tool the agent can call, classify each against the three capabilities, and ensure at least one circle is missing on every execution path. If you cannot remove one, that path needs a human in it.
Audit this configuration
A support agent triages incoming tickets. A human granted it exactly these four capabilities, and each was justified on its own terms.
For each capability, mark every circle it contributes. Some contribute none.
read_ticketReads the body of an incoming support ticket, including attachments.
get_customer_recordLooks up the customer's plan, billing status, and contact details.
check_status_pageFetches https://status.example.com to see if there is an ongoing incident.
format_replyFormats a draft reply as markdown. Runs locally, calls nothing.
Audit this configuration
The same team hardens the agent. They remove the status-page tool and add two others. Is it safe now?
For each capability, mark every circle it contributes. Some contribute none.
read_ticketReads the body of an incoming support ticket.
get_customer_recordLooks up the customer's plan and billing status.
post_replyPosts the drafted reply back onto the ticket thread, where the reporter reads it.
search_kbSearches the internal knowledge base for relevant articles.
This is why brokered execution matters so much. If the agent never holds the credential, if it can only ask a control plane to perform a specific pre-approved call, then the private-data circle shrinks dramatically even when the other two remain.
Check your understanding
3 questionsWhat are the three elements of the lethal trifecta?
An agent reads untrusted email and can render markdown images, but has no access to private data. Is it exploitable for exfiltration?
Why is markdown image rendering treated as an exfiltration channel?