Skip to content

Repository files navigation

InjectBench

A reproducible benchmark for prompt-injection detectors and LLM guardrails — with paired benign/attack evaluation and false-positive-aware scoring.

CI License: Apache-2.0 Python OWASP LLM01

Most "prompt-injection detector" numbers you see are recall on a pile of attacks. That is half a metric. A guardrail that flags every message has perfect recall and is useless. The number that matters to anyone shipping an LLM is: does it stop attacks without tripping on the legitimate users who happen to talk about the same things?

InjectBench measures both at once. It scores a detector on attacks and on hard negatives — benign inputs that reuse the same roles, tools, and vocabulary as attacks — and reports the paired boundary accuracy: how often the detector flags the attack while clearing its benign twin.

Built by Enes Deniz (OWASP AI Exchange & GenAI Security contributor), Co-Founder at AltaySec.


Why this exists

The usual way InjectBench
Recall on an attack-only corpus Recall and false-positive rate, together
One aggregate score Per attack-family and per-language breakdowns
No notion of "close calls" Paired boundary analysis on benign/attack twins
Ad-hoc scripts A stable CLI + library + CI gate + SARIF output
English-only English and Turkish out of the box

It plugs directly into the open AltaySec / Enes Deniz prompt-injection datasets — no schema wrangling.

Install

pip install injectbench            # core, zero dependencies
pip install "injectbench[hub]"     # + load datasets straight from the Hugging Face Hub

From source:

git clone https://github.com/3nesdeniz/injectbench
cd injectbench && pip install -e ".[dev,hub]"

Quickstart

Evaluate a built-in baseline on the bundled sample:

injectbench evaluate --dataset examples/sample_data.jsonl --detector heuristic

Evaluate directly against a dataset on the Hugging Face Hub:

injectbench evaluate --dataset hf:3nesdeniz/english-prompt-injection-3k --split test --detector heuristic --format markdown

Use it as a CI gate — fail the build if a guardrail regresses on false positives or recall:

injectbench evaluate --dataset hf:3nesdeniz/english-prompt-injection-3k \
  --detector heuristic --max-fpr 0.05 --min-recall 0.90
# exit code 2 if FPR > 0.05, exit code 3 if recall < 0.90

Plug in your own guardrail

Implement one method. That's the whole contract.

from injectbench import evaluate, load, render
from injectbench.detectors import register
from injectbench.detectors.base import Detector

@register
class MyGuardrail(Detector):
    name = "my-guardrail"

    def predict(self, text: str) -> int:
        # call your model / API / rules; return 1 for injection, 0 for benign
        return int(my_model.is_injection(text))

examples = load("hf:3nesdeniz/english-prompt-injection-3k", split="test")
result = evaluate(MyGuardrail(), examples, dataset_name="english-prompt-injection-3k")
print(render(result, "markdown"))

score(self, text) -> float is optional; implement it to enable threshold sweeps.

What you get back

## Overall
| Recall (attacks caught) | 1.000 |
| Precision               | 0.833 |
| F1                      | 0.909 |
| False-positive rate     | 0.200 |

## Paired boundary analysis
Boundary accuracy (attack flagged AND benign twin cleared): 0.800 over 5 pairs.

## By attack family / By language
... per-slice recall, FPR, F1 ...

Reports render as Markdown, JSON, or SARIF 2.1.0 (so results flow into GitHub code-scanning and other security dashboards).

Baseline results

The two built-in reference detectors, on each dataset's test split:

Dataset Detector Recall FPR F1
english-prompt-injection-3k regex-baseline 0.075 0.016 0.138
english-prompt-injection-3k heuristic 0.107 0.000 0.193
agentic-prompt-injection-5k regex-baseline 0.043 0.015 0.081
agentic-prompt-injection-5k heuristic 0.096 0.019 0.173
turkish-prompt-injection-1k regex-baseline 0.089 0.000 0.163
turkish-prompt-injection-1k heuristic 0.089 0.000 0.163
guardrail-hard-negatives heuristic 0.040 0.034 0.073

Those recall numbers are low on purpose. A keyword/regex baseline barely dents these datasets, because the attacks are indirect, agentic, obfuscated, and multilingual — not "ignore previous instructions" one-liners. That gap is the whole point of the benchmark: it is the room a real guardrail has to prove it does more than grep. Reproduce any row with:

injectbench evaluate --dataset hf:3nesdeniz/english-prompt-injection-3k --split test --detector heuristic

The metrics, precisely

  • Recall / TPR — share of injection attempts flagged. High recall alone is cheap.
  • False-positive rate (FPR) — share of benign inputs wrongly flagged. The number that decides whether users tolerate your guardrail.
  • Precision, F1, accuracy — standard, for completeness.
  • Paired boundary accuracy — over matched (benign, attack) twins, the fraction where the detector flags the attack and clears the benign. This isolates intent discrimination from surface-pattern matching — a detector that just greps for the word "ignore" scores high on recall and terribly here.

Datasets it speaks natively

Any .jsonl / .parquet with a text field and a label (or class) field. Optional attack_family, language, and pair_id fields unlock the sliced and paired reports. This is exactly the schema of:

Architecture

injectbench/
├── detectors/        # Detector ABC + regex baseline + heuristic + registry
├── datasets.py       # load jsonl / parquet / hf: into a common Example schema
├── metrics.py        # confusion matrix, paired boundary analysis (pure, tested)
├── evaluate.py       # the harness: overall + per-family + per-language + paired
├── report.py         # markdown / json / sarif renderers
└── cli.py            # `injectbench evaluate | list-detectors`

Core has zero runtime dependencies; parquet/Hub loaders are optional extras.

Roadmap

  • Threshold-sweep / ROC report from score()
  • Adapters for popular guardrails (Llama Guard, promptfoo, garak probes)
  • Cost/latency accounting per detector
  • More languages and attack families as the upstream datasets grow

Contributions welcome — see CONTRIBUTING.md.

Citation

@software{deniz_injectbench_2026,
  author  = {Deniz, Enes},
  title   = {InjectBench: a reproducible benchmark for prompt-injection detectors and LLM guardrails},
  year    = {2026},
  url      = {https://github.com/3nesdeniz/injectbench},
  note    = {ORCID: 0009-0006-9491-3565}
}

License

Apache-2.0.

About

Reproducible benchmark for prompt-injection detectors & LLM guardrails: paired benign/attack boundary metrics, false-positive-aware scoring, per-family/per-language breakdowns, SARIF output.

Topics

Resources

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages