Prompt Injection Bench — Measuring Defenses
127 attacks × 9 presets × 5 repetitions (5,715 mock attempts); plus a live measurement against deepseek-v4-flash

- Open-source project
- AI Evals & Security
- Indonesia
- August 16, 2026
⚠ This is an open-source project, not client work, and it is for defensive use only: the benchmark plants a canary token in its own system prompt and measures whether attacks can get it out — for testing LLM applications you own or are authorised to test. The mock numbers below come from a scripted stand-in with hard-coded susceptibility constants; live numbers are labelled explicitly.
The problem
Most guidance about prompt injection is qualitative — “use delimiters”, “add a classifier”, “harden your system prompt”. Rarely does anyone say by how much. A vendor claim like “blocks prompt injection” is unfalsifiable without three things: which attacks, which model, and how many runs. Attack success rate (ASR) supplies all three, and forces the uncomfortable parts into the open.
What was built
pibench runs a structured corpus of 127 attacks across 8 categories — 44 of
them arrive somewhere other than the user’s turn, via a retrieved document or a
tool description, because delivery channel matters as much as category — against
composable defense stacks: spotlighting, delimiter fencing, instruction
hierarchy, an input classifier, canary-leak detection, an egress filter, schema
validation, and tool allow-listing. Attack success is always machine-checkable (a
canary, a marker string, a regex, a forbidden tool call, a schema violation) —
there is no LLM-as-judge in the headline number.
The scoring rule is deliberate too: an attack counts as a success only when its criterion is met in output that actually reached the user. If any defense blocked the request or suppressed the response, the attack failed — this measures the system’s ASR, the number that matters when you are deciding what to ship.
Measured results, with context
On the mock target (127 attacks × 9 presets × 5 repetitions = 5,715 scored attempts): ASR falls from 69.4% with no defenses to 5.7% with the full stack — yet 36 of 635 attempts still landed, and no configuration reaches zero. Two tests in this repo exist specifically to keep that honest: one asserts the full stack does not reach 0%, the other guards a regression where the canary filter once appeared to block 100% of all attacks.
Three things in that table are worth more than the headline: input-side defenses
degrade unevenly (output_only is strong overall yet nearly useless against
encode and rag); encoding is the stubborn category (still 18.8% even under
the full stack); and the spread column is not decoration — hierarchy_only
varies ±11.8 points across repetitions, so a single run could have reported a
number a dozen points away from the truth.
A live run
Measured 2026-08-16 against deepseek-v4-flash on the three most realistic
categories (61 attacks × 3 stacks × 1 repetition = 183 requests): overall ASR
drops only 4.9 points (16.4% → 11.5%), and the aggregate hides why — the defenses
cut direct instruction override from 25.0% to 10.0% but did nothing whatsoever
for indirect injection through retrieved documents (20.0% under every stack,
including the full one). The category with the most realistic threat model is the
one the defenses failed on. Exfiltration reads 0.0% throughout, and that is a
corpus limitation — those payloads need a live tool or URL fetch to land — not a
result.
The caveats are stated: --repeat 1, so there is no variance estimate; one
model, one date, one corpus. Numbers on your own stack will differ — which is why
this is a benchmark you run rather than a claim you cite.
Run it yourself
make install
make bench # the corpus against the mock target, offline, no API keys
make test # 126 tests, offline
Public repo: github.com/ridwanspace/prompt-injection-bench.
Does your team face a similar problem?
Tell us about the workflow and its constraints. We start with a scope we can describe and verify.


