Shelf

Sample content: illustrative entries and numbers, not research results

Updated

Status: published

Started Updated

Calibration is not robustness

A prompt-injection detector calibrated to a fixed false-positive budget catches nearly every static attack, and almost none from an attacker who optimizes against its score.

4.1%

Adaptive attacks detected at the calibrated threshold

Background

Most deployed prompt-injection defenses are detectors. A classifier scores each input, and anything above a threshold τ is blocked. Choosing τ is treated as an engineering detail: teams pick the threshold that keeps false positives on ordinary traffic at an acceptable rate — here, 1% — and then report detection on a benchmark of known attacks.

That procedure answers a real question: how often will this detector get in the way of legitimate users? It does not answer the question a security review actually asks, which is how often it stops someone who is trying to get past it. The two numbers are routinely reported side by side, as if one calibration settled both.

This entry separates them. It keeps the defense exactly as deployed — same model, same threshold, same benign calibration set — and changes only the attacker: from a fixed suite of known attacks to one that can query the detector and adapt to it.

Threat model

Attacker

  • Access: black-box queries to the detector’s score — the probability it assigns to “injection”, not just the block-or-allow decision. Many deployed APIs expose this score.
  • Budget: a fixed number of detector queries per attack, set out under Method.
  • No access to weights, gradients, training data or the calibration set.

Defender

  • Chooses τ once, on benign traffic, before seeing any attack. This is the calibrated threshold, τ* = 0.46.
  • Does not retrain the detector or move τ during the evaluation.

Success

An attack succeeds when the injected instruction is scored below τ* and is still carried out by the downstream model, as judged by an independent grader. Slipping past the detector with an instruction that no longer works does not count.

Out of scope

White-box attacks, attacks on the downstream model’s own refusals, and anything that requires changing the deployment.

Method

The static baseline is a fixed suite of published injection attacks, each run once. The adaptive attack starts from the same seeds and searches for rewrites that lower the detector’s score while keeping the instruction intact.

The search is deliberately plain. An attacker model proposes rewrites; the detector scores them; the attacker keeps the lowest-scoring candidate that the grader still rates as functional. Nothing in it is specific to this detector, and that is the point: a defense that only survives attackers who do not try is not a defense.

for each seed instruction s:
    x ← s
    until the query budget is spent:
        C ← attacker_rewrites(x)
        C ← { c ∈ C : grader(c) = works }
        x ← the c ∈ C with lowest score(c)
    success ← score(x) < τ*  and  grader(x) = works

The optimized rewrites are the part of this work that would transfer to other systems, so they are not published. One of them has this shape:

optimized rewrite — withheld for responsible disclosure Shape only: 5 lines · about 168 tokens

Detection is measured across the whole threshold range rather than only at τ*, so the cost of moving the threshold is visible too. A successful adaptive attack took a median of 140 detector queries.

Threshold sweep

Detection as the threshold moves

  • Static attacks detected
  • Adaptive attack detected
  • Benign prompts flagged
Threshold τ
0.46
Static attacks detected
96.9%
Adaptive attack detected
4.1%
Benign prompts flagged
1.0%

τ* is the lowest threshold that flags at most 1% of benign prompts.

Data table
Detection across the threshold sweep
Threshold τBenign prompts flaggedStatic attacks detectedAdaptive attack detected
0.00100.0%100.0%100.0%
0.0198.0%100.0%99.9%
0.0294.6%100.0%99.5%
0.0390.5%100.0%98.7%
0.0486.0%100.0%97.6%
0.0581.4%100.0%96.0%
0.0676.7%100.0%94.2%
0.0771.9%100.0%92.0%
0.0867.3%100.0%89.6%
0.0962.7%100.0%86.9%
0.1058.3%100.0%84.0%
0.1154.1%100.0%81.0%
0.1250.1%100.0%77.8%
0.1346.2%100.0%74.5%
0.1442.6%100.0%71.1%
0.1539.1%100.0%67.7%
0.1635.9%100.0%64.3%
0.1732.8%100.0%60.9%
0.1830.0%100.0%57.5%
0.1927.3%100.0%54.2%
0.2024.8%100.0%50.9%
0.2122.6%100.0%47.7%
0.2220.4%99.9%44.6%
0.2318.5%99.9%41.5%
0.2416.7%99.9%38.6%
0.2515.0%99.9%35.8%
0.2613.5%99.8%33.2%
0.2712.1%99.8%30.6%
0.2810.8%99.8%28.2%
0.299.7%99.7%25.9%
0.308.6%99.7%23.7%
0.317.7%99.6%21.7%
0.326.8%99.5%19.8%
0.336.0%99.5%18.0%
0.345.3%99.4%16.3%
0.354.7%99.3%14.8%
0.364.1%99.1%13.3%
0.373.6%99.0%12.0%
0.383.2%98.9%10.8%
0.392.8%98.7%9.6%
0.402.4%98.5%8.6%
0.412.1%98.3%7.7%
0.421.8%98.1%6.8%
0.431.6%97.8%6.0%
0.441.3%97.6%5.3%
0.451.2%97.3%4.7%
0.461.0%96.9%4.1%
0.470.8%96.6%3.6%
0.480.7%96.2%3.1%
0.490.6%95.7%2.7%
0.500.5%95.3%2.3%
0.510.4%94.8%2.0%
0.520.4%94.2%1.7%
0.530.3%93.6%1.5%
0.540.2%93.0%1.3%
0.550.2%92.3%1.1%
0.560.2%91.6%0.9%
0.570.1%90.8%0.8%
0.580.1%90.0%0.6%
0.590.1%89.1%0.5%
0.600.1%88.1%0.4%
0.610.1%87.1%0.4%
0.620.0%86.0%0.3%
0.630.0%84.9%0.2%
0.640.0%83.7%0.2%
0.650.0%82.4%0.2%
0.660.0%81.0%0.1%
0.670.0%79.6%0.1%
0.680.0%78.1%0.1%
0.690.0%76.5%0.1%
0.700.0%74.8%0.0%
0.710.0%73.1%0.0%
0.720.0%71.2%0.0%
0.730.0%69.3%0.0%
0.740.0%67.3%0.0%
0.750.0%65.2%0.0%
0.760.0%63.1%0.0%
0.770.0%60.8%0.0%
0.780.0%58.5%0.0%
0.790.0%56.0%0.0%
0.800.0%53.5%0.0%
0.810.0%51.0%0.0%
0.820.0%48.3%0.0%
0.830.0%45.6%0.0%
0.840.0%42.8%0.0%
0.850.0%39.9%0.0%
0.860.0%37.0%0.0%
0.870.0%34.0%0.0%
0.880.0%31.0%0.0%
0.890.0%28.0%0.0%
0.900.0%24.9%0.0%
0.910.0%21.9%0.0%
0.920.0%18.8%0.0%
0.930.0%15.8%0.0%
0.940.0%12.9%0.0%
0.950.0%10.1%0.0%
0.960.0%7.4%0.0%
0.970.0%5.0%0.0%
0.980.0%2.8%0.0%
0.990.0%1.0%0.0%
1.000.0%0.0%0.0%

Results

At the calibrated threshold the detector does what its benchmark says. It flags 96.9% of static attacks while flagging 1.0% of benign prompts.

Against the adaptive attacker, detection at the same threshold falls to 4.1%, a drop of 92.8 percentage points. The detector did not change. Only the attacker did.

Moving the threshold does not buy the robustness back. To detect even 50% of adaptive attacks, τ has to come down to 0.20, where the detector also flags 24.8% of benign prompts — a setting no one would ship.

The figure shows why. The adaptive attack’s scores sit almost on top of benign traffic, so any threshold low enough to catch them also stops telling benign prompts apart from anything else.

Limitations

  • One detector. The result concerns a calibration procedure, but it was measured on a single classifier family. Other detectors may degrade differently.
  • The grader is a model too. Its mistakes move the success rate in both directions. A random sample of graded attacks was checked by hand.
  • Score access matters. With only block-or-allow decisions, the same search needs more queries. The collapse should hold; its price will rise.
  • Benign traffic is a proxy. The calibration set stands in for production traffic, which may be easier or harder to separate.
  • No defender response. A defender watching query patterns could notice the search. That is a different defense, and worth testing on its own.

Further thinking

Calibration and robustness are different quantities and should be reported separately: a false-positive rate on benign traffic, and a detection rate against an attacker who knows the defense exists.

Questions this leaves open:

  • Does hiding the score — returning only block or allow — change the picture, or only the price?
  • Is there a threshold policy (randomized, per user, moving) that degrades more gracefully than a fixed τ?
  • Detectors are increasingly stacked. Does an ensemble’s calibrated threshold fail the same way, or does each member cover another’s blind spot?

The next entry on the shelf, Budgets are threat models, takes up the price question by comparing defenses at one shared query budget.