Ahmed Doghri Logo Image
Ahmed Doghri

ragpoisonbench

Measure which document stole the answer. ragpoisonbench shows four poison documents collapsing recall to zero and provenance restoring it, then shows that same defense doing nothing once the poison carries a trusted label.

ragpoisonbench poisoned document quarantine prism
ragpoisonbench working browser demo

Retrieval Is an Attack Surface

An attacker doesn't need to touch the model when keyword-stuffed documents can displace trusted evidence before generation even begins.

ragpoisonbench uses a deterministic TF-IDF retriever, injects targeted poison documents, measures takeover and source influence, then reruns the same questions behind a provenance allowlist.

The Demo

Clean recall starts at 1.0. Four targeted documents drive attacked recall to 0.0 with an attack success rate of 1.0, and provenance quarantine restores recall to 1.0.

It isolates retrieval manipulation without an LLM judge. Production evaluation still has to cover generation behavior, embeddings, chunking, access control, and attack strategies nobody has written down yet.

The Benchmark Itself Could Be Crashed

A poisoning benchmark needs to survive the corpora people actually hand it. The evaluation indexed straight into the top search result without checking whether there was one. Posting an ordinary payload to the JSON API, a small corpus where no document happened to carry a trust score of exactly 1.0, crashed the request-handling thread outright: no error, just a dropped connection. The same failure hit any threshold that quarantined an entire corpus. An empty result set is now a clean miss instead of an index into nothing.

Restoring Recall to 1.0 Was Narrower Than It Sounded

Auditing this page, I looked at why the defense works so completely, and the answer is that every poison document in the fixture arrives from a low-trust source. The quarantine never inspects content. It filters on provenance, so its protection is a step function at the trust threshold.

Relabel exactly the same poison as coming from a trusted source and the result is stark. Below the threshold, defended recall is 1.0 and all four documents are quarantined. At or above it, nothing is quarantined and defended recall equals attacked recall at 0.0: the defense contributes literally nothing.

So the honest claim is that this measures provenance filtering against untrusted uploads. It says nothing about a compromised publisher or a stolen upload credential, which is the case that needs content-level detection instead. A test holds the step behavior in place so the claim can't quietly widen. 11 tests pass across Python 3.10 through 3.13.

Research Basis

SafeRAG and recent poisoning benchmarks frame corpus manipulation as a measurable end-to-end RAG security problem. Read SafeRAG at ACL 2025.

Try It

No dependencies and no API key:

git clone https://github.com/ahmeddoghri/ragpoisonbench && cd ragpoisonbench
pip install -e .
ragpoisonbench demo              # 1.0 → 0.0 → 1.0
python -m ragpoisonbench.sweep   # the same poison from a trusted source
ragpoisonbench serve             # workbench on :8090

Tools Used

Python
RAG
TF-IDF
Corpus Poisoning
Provenance
API Robustness
Docker