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