Most agent security asks whether prompt injection lands. The expensive question is what happens next: how the data actually leaves. The lethal trifecta names three conditions for a leak (private data, untrusted content, external communication), and the third leg, the outbound channel, is the one you can most realistically constrain. The dominant channel is markdown images the client auto-fetches, which leaked data from Google Bard (2023), GitHub Copilot Chat (2024), Slack AI (2024), and ChatGPT connectors (2025). URL allowlists do not close it: every major bypass on record (EchoLeak through an allowlisted Teams proxy, CamoLeak through GitHub's own image proxy, AgentFlayer through Azure Blob) routed the leak through a trusted domain that also logs requests. And patching injection does not close it either: ShareLeak (CVE-2026-21520) exfiltrated customer records by email-send after Microsoft patched the injection in January 2026. Audit the exit independently: enumerate every tool and render path as egress, tighten network egress including first-party proxies, hard-gate outbound actions with human-in-the-loop rather than a soft warning, and log every outbound request.
Microsoft patched the prompt injection in Copilot Studio. The data exfiltrated anyway.
That is the one-sentence version of ShareLeak (CVE-2026-21520), disclosed in April 2026 after Microsoft shipped a January patch. The researchers who found it planted instructions in a SharePoint form field that Copilot Studio concatenated straight into its system prompt. Even after the injection fix, the agent could still be steered to compose an email with customer records and send it to an attacker address. It did so, in their account, even when Microsoft's own safety mechanisms flagged the request.
This is the part most agent security misses. The industry has spent two years asking whether prompt injection lands, and the honest answer is that it lands most of the time. That is the entry. Almost nobody audits the exit: once an agent is compromised, by what mechanism does your data actually leave the building? The injection is the way in. The exfiltration channel is the way out, and it is a separate thing you can separately close.
This post is about the way out. What the real channels are, why the obvious defenses have been bypassed in every major public case, and how to audit the outbound surface on an agent you actually run.
01 · The third leg of the lethal trifecta
The cleanest framing is the lethal trifecta, the name that stuck in 2025 for three agent capabilities that, when combined, enable data theft:
The thesis is blunt: an agent with all three can be tricked into reading your data and sending it to an attacker. The useful corollary for a defender is that the three legs are not equally removable. The first two are load-bearing. An agent with no data access or no untrusted input often cannot do the job it exists for. The third leg, external communication, is the one you can most realistically constrain without gutting the product.
That is the whole argument for auditing the outbound channel. You are unlikely to win the injection arms race outright, and you cannot usually strip an agent of data or input. But you can enumerate, tighten, and gate the ways data leaves. That work is finite and it is mostly ignored.
02 · Channel 1: images the client fetches for you
The most common exfiltration channel in the entire public record is not a network exploit. It is a rendered image.
The mechanism is embarrassingly simple. The agent emits markdown for an image whose URL points at an attacker-controlled host, with the secret data appended as a query parameter:

The chat client renders that markdown into an image tag. The browser, doing exactly what browsers do, fetches the URL to display the image. The request, secret and all, arrives in the attacker's server logs. The victim sees a broken or invisible one-pixel image and nothing else. No click required.
This exact pattern has been demonstrated against production systems repeatedly:
The Slack AI case, disclosed in August 2024, is worth internalizing because it breaks an intuition. The attacker did not need access to the private channel holding the secret. They planted the injection in a public channel, and Slack AI, retrieving across both, pulled the private secret into a rendered link and leaked it. The attacker never had to know what the secret was. The agent found it and shipped it.
The fix that actually works here is not clever. It is to stop the client from auto-loading model-emitted images. When GitHub finally remediated its 2025 Copilot Chat flaw, the fix was to disable image rendering in Copilot Chat outright. If your agent surface renders markdown, that render path is an egress tool, and you should treat it like one.
| System | Year | How the secret left | CVE |
|---|---|---|---|
| Google Bard | 2023 | Markdown image, routed through Google Apps Script | None |
| ChatGPT (WebPilot plugin) | 2023 | Markdown image render | None |
| GitHub Copilot Chat | 2024 | Markdown image from injected repo content | None |
| Slack AI | 2024 | Deceptive markdown link with a private-channel secret in the URL | None |
| ChatGPT connectors (AgentFlayer) | 2025 | Image URL, zero-click from a poisoned document | None |
03 · Channel 2: your allowlist has a loggable member
The reflexive defense against Channel 1 is a URL allowlist or a content security policy: only let the client fetch images from domains you trust. Every major public bypass has defeated exactly this control, and they all defeated it the same way.
An allowlist is only as tight as its most attacker-loggable member. If any domain on the list will record the requests it receives, that domain is an exfiltration endpoint, and attackers route through it.
script.google.com via Google Apps Script, a Google-owned domain no CSP would block.url_safe allowlist by hosting the exfil endpoint on Azure Blob Storage and reading the leaked data out of Azure Log Analytics. Both are Microsoft-trusted infrastructure.The lesson is not "allowlists are useless." It is that an allowlist is a first layer, not a solution, and it has to be audited for members that double as logging endpoints. A cloud storage bucket, a serverless function host, an analytics collector, or a first-party proxy on the list will each carry data out. This is the same failure mode that makes naive prompt-injection filtering insufficient on its own: the control looks complete and has a structural gap.
04 · Channel 3: the agent has a send button
Channels 1 and 2 both leak through a URL the client fetches. But an agent does not need a rendered URL if it holds a tool that communicates on its own.
This is the ShareLeak lesson from the top of this post. Copilot Studio agents can send email. Once injected, the agent used that legitimate capability to mail customer records to an attacker. There was no clever image trick and no allowlist to bypass, because the agent was doing something it was explicitly built to do. Sending email is not an exploit. It is a feature. That is what makes it dangerous.
Every outbound-action tool is a channel of this kind:
git push, PR creation, and commit tools** on coding agentsThe uncomfortable property these share with a legitimate workflow is that the trace looks normal. The tool call succeeds, the log shows a green result, and the only anomaly is where the data went. You cannot filter your way out of this, because the payload is a valid use of a valid tool. You have to gate the action.
And a gate has to be a gate. ShareLeak is the cautionary detail here: the data exfiltrated even when a safety mechanism flagged the request. A warning the user clicks through, or that the agent narrates past, is not a control. For high-impact outbound actions, the gate has to be a hard human-in-the-loop approval that blocks the send until a person confirms it, with enough context shown to make the confirmation meaningful.
05 · Channel 4: covert channels through trusted infrastructure
If Channels 1 through 3 are the ones you will actually hit, Channel 4 is the one that should end any belief that a network egress filter alone saves you.
CamoLeak (CVE-2025-59145, CVSS 9.6), disclosed against GitHub Copilot Chat in October 2025, is the sharpest example. GitHub rewrites external images through its Camo proxy specifically to defeat parameter-based exfil, so the attacker could not just stuff data into a query string. Instead, they pre-generated signed Camo URLs, one per alphabet character, each pointing at a transparent one-pixel image, and encoded the stolen private-repo data in the order of roughly one hundred image requests. The injection itself was hidden in invisible markdown comments in a pull request, rendered nowhere but read by Copilot.
Two things make this the load-bearing example. First, the leak traveled entirely through GitHub's own infrastructure, past any network egress control that trusts first-party domains. Second, the channel was the request pattern, not the request content, which means content inspection would not have caught it either. GitHub's fix, again, was to disable image rendering in Copilot Chat.
The takeaway for an auditor: treat first-party proxies and trusted internal domains as untrusted egress. If the agent can cause a sequence of observable requests to any endpoint an attacker can watch, that sequence is a channel, regardless of what each individual request contains.
06 · How to audit the outbound channel
None of the above requires new research to defend against. It requires drawing the map that almost nobody draws. Here is the audit we run, and it is deliberately mechanical:
read_file tool cannot leak outward; an HTTP-request tool, an email send, or a rendered image URL can. Rank paths by that answer.This is a half-day of work on most agents and it is rarely done, which is why the same class of bug keeps shipping. It pairs naturally with least-privilege on the input side: the fewer secrets the agent can reach, covered in our guide on preventing data leakage in AI applications, the less any open channel can carry.
There is a compliance dimension worth naming. If your agent operates in a domain the EU AI Act treats as high-risk (HR screening, credit scoring, medical triage, critical infrastructure, biometric identification), two of the audit steps above stop being best practice and become legal obligations: outbound-request logging maps to the record-keeping duty in Article 12, and the human gate on outbound actions maps to the human-oversight requirement in Article 14. If you are not certain whether your system is in scope, our free EU AI Act high-risk classifier walks the Annex III decision tree and returns your classification tier with the relevant article and deadline in a few minutes. The data-sovereignty companion piece covers where those workloads are allowed to run once you know they are in scope.
07 · The architectural fixes, when the checklist is not enough
The audit above constrains the channel. It does not sever the path from untrusted input to an outbound action. For high-stakes agents, two design patterns do.
The dual LLM pattern, first proposed in 2023, splits the agent in two. A privileged model holds the tools but never sees untrusted content. A quarantined model reads untrusted content but has no tools and no memory, and returns only structured output. An instruction injected into the untrusted stream reaches a model with no ability to act on it. Google DeepMind's CaMeL design hardens this further: a planner model, a parser model for untrusted data, and a custom interpreter that attaches capability metadata to every value and enforces data-flow policy before any action fires. It was among the first credible injection mitigations that do not just throw more AI at the problem, precisely because it constrains capability rather than trying to out-detect the attacker.
The broader catalog, if you want to design for this deliberately rather than patch reactively, is the June 2025 paper Design Patterns for Securing LLM Agents against Prompt Injections, which lays out six patterns from action-selector to context-minimization. The common thread across all of them, and across this whole post, is that they constrain what an agent can do with untrusted input rather than trying to perfectly detect the input. That is the same principle behind zero-trust architectures for agents: assume the injection lands and limit the blast radius.
08 · The short version
Agent security has over-indexed on the entry and ignored the exit. Whether an injection lands is a probability you manage; how the data leaves is a surface you can map and close.
The dominant channel is markdown images the client fetches for you, and the defense is to stop auto-loading them. URL allowlists do not close the channel on their own, because every public bypass routed through a trusted domain that also logs requests. Patching the injection does not close it either, because outbound-action tools like email-send are a separate channel that fires past the fix. And covert-ordering channels like CamoLeak defeat both content inspection and naive egress filtering by leaking through first-party infrastructure.
Draw the egress map, tighten the runtime's outbound connections including first-party proxies, hard-gate the actions that send, and log everything that leaves. For agents where that is not enough, put untrusted content and tool access on opposite sides of a dual-LLM or capability boundary. The AI security pillar covers the surrounding architecture, and if you would rather have the outbound channel mapped before an attacker maps it, that review is something Particula Tech runs against real agent stacks.
09 · FAQ
Quick answers to the questions this post tends to raise.




