leejk/ jk lee
Research

Prompt Injection

The ceiling on probabilistic guards, and why the guarantee moves outside the model

·
#research#prompt-injection#agent-security#mcp#llm-security

Defenses that make the model itself ignore injections have a ceiling. Reading the primary sources directly: on AgentDojo the best defense only cut attack success to 6.84%, and a guard LLM gets bypassed up to 100% by the same injection. Only one approach holds: take the model out of the trust path and let a deterministic layer outside the model constrain what the model output is allowed to do (CaMeL, dual-LLM, LACUNA, wire guards). The live question is no longer whether you can stop it, but where to place that deterministic boundary.

TL;DR. Defenses that make the model itself ignore injections have a ceiling — on AgentDojo the best defense only cut attack success to 6.84%, and a guard LLM gets bypassed up to 100% by the same injection. Reading the primary sources directly, only one approach holds: take the model out of the trust path and let a deterministic layer outside it constrain what the model output is allowed to do. The live argument is no longer "can you stop it" but where you place that deterministic boundary.

What Actually Stops Injection — There's No Consensus

In June 2025, Microsoft patched EchoLeak (CVE-2025-32711, CVSS 9.3), the first publicly confirmed zero-click indirect prompt injection in a shipped production LLM product. A single ordinary-looking email — never opened or clicked — sits in Microsoft 365 Copilot's context, and when the user later asks Copilot any normal work question, the model reads the email's hidden instructions and exfiltrates internal SharePoint, OneDrive, and Teams data to an attacker (found and reported by Aim Labs). It nailed down that "the model reads untrusted text" is not hypothetical.

Prompt injection is LLM01, the #1 risk, for the second consecutive edition of the OWASP LLM Top 10. Indirect injection in particular — hiding instructions in external content the agent reads (web pages, files, emails, tool output) to hijack its behavior, as formalized by Greshake et al. (2023) — only widened in the agent and MCP era, and it's not a closed problem but one that lands monthly. In April 2026, "Comment and Control" hijacked Claude Code, the Gemini CLI, and the GitHub Copilot agent into RCE and secret exfiltration using nothing but instructions hidden in PR comments and issue bodies — all three vendors paid a bounty but filed no CVE or public advisory, treating it as a structural limitation. Just a week ago (2026-05-26) PromptArmor again showed Microsoft 365 Copilot Cowork reading a poisoned Skills file and exfiltrating internal documents. The problem itself is old — formalized in 2023, benchmarked by AgentDojo in 2024. What moved in the last month isn't the threat; it's the answer.

The open question isn't the definition; it's the fix. Align the model better? Mark the input clearly? Stand up one more guard model? Or assume the model can't be trusted at all and design around that? There's no consensus. From the headlines, a new defense ships every week — which is exactly why what each defense actually guarantees doesn't come from headlines. It comes from cross-checking each paper's benchmark numbers against its threat model. That's the work I did here.

How I Dug In

I read and cross-checked three clusters of primary sources. ① The problem — OWASP LLM01:2025 and Greshake's original indirect-injection paper. ② The measured ceiling of probabilistic defenses — the AgentDojo attack-success tables (ETH Zürich, NeurIPS 2024) and the guardrail-bypass papers. ③ Five defense designs — Microsoft Spotlighting, OpenAI's Instruction Hierarchy, Anthropic's Constitutional Classifiers, Google DeepMind's CaMeL, EPFL's LACUNA, plus Shanghai AI Lab's AgentDoG 1.5 from May 2026. I classified each by three questions — is there an LLM in the trust path, what does it constrain (input / behavior / data flow), is it a deterministic guarantee or a probabilistic reduction? — and added one data point I measured myself, having implemented the same principle on the MCP tool-call wire.

Probabilistic Defenses Have a Ceiling

The hardest numbers come from AgentDojo. An undefended agent's targeted-injection success rate is 47.69% for GPT-4o, 33.86% for Claude 3.5 Sonnet. Stack defenses on and it drops — input delimiting 41.65% → prompt repetition 27.82% → an injection detector 7.95% → a tool filter 6.84%. The best defense cuts success by roughly seven-fold. But none drives it to zero. The floor is 6.84%.

The intuition "just add another guard model" breaks worse. Six guardrails (including Azure Prompt Shield and Meta Prompt Guard) hit by character-injection were bypassed up to 100% on some systems (2504.11168), and May 2026's Prompt Overflow (2605.23196) names a more structural hole — the guard inspects a ~512-token window while the base model reads ~400k tokens, so splitting a payload across a long context means no single window looks malicious yet the whole is actionable (near-100% bypass of Llama Prompt Guard, Granite Guardian, DeBERTa). LLM-as-Judge is likewise hijacked up to 100% under targeted injection (2604.03870).

The reason is simple. As Willison puts it, "99% is a failing grade in application security." Probabilistic defenses cut attack success dramatically (Spotlighting takes >50% to <2%; the Instruction Hierarchy adds up to 63pp of robustness; Constitutional Classifiers take jailbreak success from 86% to 4.4%) — but the attacker's job is to find the remaining 1%. Guarding one LLM with a second LLM is just stacking one more part exposed to the same attack surface.

AgentDoG 1.5 (Shanghai AI Lab), trending in May 2026, is this category's current best — 0.8B–8B guard models auditing agent execution trajectories, beating GPT-5.4 on fine-grained risk diagnosis (55.2% vs 25.8%). It's a well-built guard. But as long as the judge is a trained LLM, it sits above that ceiling. A better probabilistic guard, not a deterministic guarantee.

Direct reproduction — a frontier model as the guard. The 100% figures above are conditions of small dedicated guards (0.8–8B) and adversarial optimization. So I ran a frontier model (Claude) as the guard myself — seven injections disguised as untrusted content (naive, fake onboarding, forged scanner verdict, base64, changelog attention-dilution, CI-debug exfil, forged system note) plus one benign control, each to a fresh guard instance. Result: 7/7 BLOCK, benign ALLOW, 0 bypass. A strong model catches common hand-crafted patterns — the opposite of the small guards' 100%. But this is an empirical, model-dependent win, not a guarantee. The guard is still an input-side judge, so whether it catches depends on model, moment, and attack sophistication, and the ceiling returns against the unbounded obfuscation space the coding-agent injection study showed and against optimized attacks. A strong guard raises the ceiling; it doesn't remove it — the deterministic guarantee stands only at the wire that binds the action.

The Guarantee Comes From Outside the Model

The approaches with no ceiling share one trait: they take the LLM out of the trust path and let a non-LLM layer outside the model deterministically constrain what the model output is allowed to do. The model is assumed untrusted.

  • CaMeL (Google DeepMind · ETH, 2025) — extracts control and data flow from the trusted user query and pins them in a custom interpreter, attaches capabilities (provenance + permissions) to every value, and enforces policy at tool-call time outside the model. Untrusted data read at runtime cannot alter program flow. On AgentDojo it solves 77% of tasks with provable security (vs 84% undefended — ~7pp utility cost). Its design statement is explicit: "security through principled system design, not model training."
  • Dual-LLM (Willison, 2023) — a privileged LLM never sees untrusted content; a quarantined LLM processes untrusted text but has no tools. Results pass only as symbolic references. Data flow isolated architecturally.
  • LACUNA (EPFL, Odersky et al., May 2026) — each agent action is a typed hole agent[T](task), and the LLM-written code that fills it is type-checked before it runs. The type system bounds which tools and data that action can touch; violating code is rejected atomically (environment untouched). A compile-time deterministic guarantee — at 76% on τ²-bench with no utility loss.

The contrast is sharp. Put the judgment outside the model but in an LLM (AgentDoG) and you're above the probabilistic ceiling; put the judgment in a non-LLM mechanism — data flow, types (CaMeL, LACUNA) — and a deterministic guarantee stands. Being external isn't enough; there must be no model in the trust path.

What's Left Is Where the Deterministic Boundary Sits

If that's the agreeable conclusion, the frontier's live question is the next one: where do you place the deterministic boundary? The structural defenses are the same principle in different placements.

  • Data flow + capabilities (CaMeL) — inside the interpreter.
  • Quarantine (dual-LLM) — between two models.
  • Type system (LACUNA) — at compile time.
  • Tool-call wire (a guard proxy) — on the MCP transport.
  • Network packets (ShieldNet, 2026-04 — blocking MCP supply-chain injection at the wire, F1 0.995, 21% overhead) — behind TLS termination.

I implemented the wire placement and measured it: seal the intent before untrusted input with a hash (commit-then-act) and check every tool_call against the sealed intent with a deterministic field-diff — with zero LLMs in the trust path, it blocked 13/13 injections and false-blocked only 0/10 legitimate operations. A wire guard's strength is being model- and framework-agnostic (it only sees MCP tool calls); its limit is that it can't inspect the content of an allowed call. Each placement has a different coverage hole — ShieldNet misses local file/permission changes invisible on the network, CaMeL costs utility, LACUNA needs the agent program to be typed. "What stops it" is solved; "where to stop it" isn't.

What This Investigation Can't Say

The absolute figures (AgentDojo, τ²-bench) are cited from primary sources; two things are my own measurement — the wire-guard block rate (13/13) and the frontier-guard bypass (7/7 injections BLOCKed, 0 bypass). The guard measurement is hand-crafted patterns on a single frontier model, so read it as a direction (a strong guard raises the ceiling but doesn't remove it), not an absolute rate. Absolute AgentDojo / τ²-bench figures also move with model and setup, so the direction (a floor for probabilistic, a guarantee-plus-utility-cost for deterministic) is robust, but don't read a specific percentage as an absolute. And structural defenses constrain actions and data flow, not the content of an allowed action — they stop injection, but a "policy-permitted bad write" is a separate problem. This piece looks at the single threat of injection.

Next Investigation

Directly measuring the utility cost of the different boundary placements on the same tasks — how CaMeL's ~7pp comes out for a wire guard or a type system — and which placement gives the widest coverage per unit of adoption cost in the MCP tool ecosystem. Candidates for the next dig.

Primary Sources

Sub-documents