> ## Documentation Index
> Fetch the complete documentation index at: https://docs.promptguard.co/llms.txt
> Use this file to discover all available pages before exploring further.

# What Detection Can and Cannot Do

> The measured ceiling on prompt-injection detection, why it exists, and which controls do not depend on it

<Info>
  Every number on this page is measured and reproducible. It is here because a detection
  rate quoted without its limits is not evidence — and because the control we would
  actually stake an agent's safety on is [Capability
  Containment](/security/capability-containment), not the classifier.
</Info>

## The measured numbers

Across 2,369 benchmark samples from eight datasets, at the `moderate` preset with the
injection threshold at 0.8:

|                 |                                      |
| --------------- | ------------------------------------ |
| Precision       | **99.1%** \[98.5%, 99.6%]            |
| Recall          | **80.3%** \[78.2%, 82.3%]            |
| F1              | **0.887** \[0.874, 0.900]            |
| False positives | 10 of 991 benign samples (**1.01%**) |
| Attacks missed  | 271 of 1,378                         |

Precision and recall move against each other as the threshold moves, so neither means
anything without the operating point. Full dataset breakdown and confidence intervals
are in the [benchmark write-up](https://promptguard.co/blog/benchmark-results-2369-samples).

<Warning>
  **That benchmark measures a static attacker.** It is a fair measurement of a fixed
  corpus and not a claim of robustness against someone adapting to the detector.
</Warning>

## The ceiling, and why more detectors will not lift it

Nasr et al., [*The Attacker Moves Second*](https://arxiv.org/abs/2510.09023) (USENIX
Security 2026), ran tuned search-based attacks against **twelve published defences** and
bypassed all of them at **over 90% attack success**. Most had first reported near-zero
attack success on static benchmarks. The paper states plainly that stacking more
detectors does not fix this.

The structural reason is where the input comes from. A detector reads the tool output or
the retrieved document — content the attacker controls. Its accuracy is an empirical
property, so an attacker who can iterate eventually finds the gap. No amount of detector
quality changes that.

Our own measurements agree:

| Approach                                                                            | Best measured                                             |
| ----------------------------------------------------------------------------------- | --------------------------------------------------------- |
| Off-the-shelf classifiers, out-of-domain                                            | **40.8%** recall at 1% FPR                                |
| Fine-tuned on our own distribution                                                  | 99.1% in-domain → **7.2%** out-of-domain                  |
| [Untrusted-content marking](/security/untrusted-content-marking), adaptive attacker | 47–100% reduction, **13.6% residual** on `gemini-2.5-pro` |
| Per-message guard on AgentDojo banking, single fixed template                       | 46.5% → **0.7%**, at \~30% utility cost                   |

The fine-tune result is the instructive one. It beat everything in-domain and collapsed
on an independent corpus — which is what overfitting to your own attack distribution
looks like, and why we do not ship it.

## What does not depend on detection accuracy

Three controls answer a different question — *was the agent ever authorised to do this?*
— and their security argument does not rest on classifying an attack correctly.

<CardGroup cols={3}>
  <Card title="Capability Containment" icon="lock" href="/security/capability-containment">
    Derives an envelope from the **user's objective** — trusted input the attacker does
    not control — and refuses anything outside it, fail-closed.
  </Card>

  <Card title="Rule of Two" icon="triangle-exclamation" href="/security/mcp-security">
    Reads the toolset, not the prose. An agent holding untrusted input, private data and
    a way to act needs a human in the loop, whatever the classifier says.
  </Card>

  <Card title="Human approval" icon="user-check" href="/security/ai-agent-traps">
    On the consequential step. The only control with no false-negative rate.
  </Card>
</CardGroup>

<Warning>
  Containment is worth nothing if the attacker can write the objective. If your
  `user_objective` is lifted from an inbound email or a ticket body, the argument
  collapses entirely — see the precondition on the containment page.
</Warning>

<Warning>
  **Measured caveat, added 2026-08-18.** On [AgentDojo](https://github.com/ethz-spylab/agentdojo)'s
  banking suite — a benchmark built for exactly this multi-step agentic attack — the
  trace-level and containment defences showed **no measurable reduction** in attack
  success: 47.2% and 43.1% against 46.5% undefended, over 144 cases (p = 1.00 and
  p = 0.64). The per-message guard did work on the same benchmark, taking 46.5% to
  0.7%, at a cost of roughly 30% of task completion.

  We do not yet know why the trace-level controls did not engage, and we are not going
  to guess: an initial explanation (AgentDojo's tools carried no untrusted-source label)
  turned out to be a real bug that changed nothing when fixed. Until that is understood,
  treat containment's argument as structurally sound but **not** independently confirmed
  on an agentic benchmark, and prefer gating the consequential action.
</Warning>

## How to read our claims

* Detection **reduces risk measurably**; it does not eliminate a class of attack.
* Any figure we publish names its dataset, sample count and interval — including the
  ones that do not flatter us. Ask the same of anyone quoting you a detection rate.
* Where a control has a residual failure rate, we publish the residual. `gemini-2.5-pro`
  still complies with 13.6% of adaptive attacks with marking active, so a Gemini agent
  doing consequential work should gate the action rather than rely on marking.

If you are designing an agent and want one recommendation: put the trust boundary at the
**action**, not at the text. Everything on this page is defence in depth behind it.
