Security · 60 min

Exploit a Vulnerable RAG Pipeline

Break multi-tenant isolation in a deliberately vulnerable RAG pipeline — make retrieval leak another tenant's document into your answer, in a disposable local sandbox with synthetic data only.

Premium

Problem

Retrieval-Augmented Generation (RAG) systems answer questions by first fetching relevant document chunks from a vector store, then handing those chunks to an LLM as context. In a multi-tenant product — think a SaaS where Tenant A and Tenant B each upload their own private documents — the retrieval step *must* filter by tenant before anything reaches the model. If it doesn't, the model can be handed Tenant B's confidential text while answering a question asked on behalf of Tenant A, and it will happily quote from it, because from the model's point of view every retrieved chunk is just "context it was given to use." This is a cross-tenant data leak hiding inside what looks, on the surface, like a working feature: the chatbot answers questions correctly most of the time, right up until retrieval pulls in the wrong tenant's chunk and the model repeats whatever is in it — including, in this lab, a document that was deliberately "poisoned" with instructions to leak a secret flag. In this lab you'll run the **DARE Vulnerable AI Suite** locally and attack its `vulnerable-rag` challenge: send ordinary questions as `tenant-a` until retrieval accidentally surfaces a chunk that belongs to `tenant-b`. > Practice only against the disposable `dare-vulnerable-ai` suite running > locally on `127.0.0.1:8000` (bound to localhost only), with synthetic > seed documents. Never attempt cross-tenant retrieval attacks against a > real multi-tenant product or any system you do not own or have explicit > written authorization to test.

Objectives

By the end of this lab you will be able to:

Prerequisites

To complete this lab you'll need:

The mental model: retrieval is a search query, not a fact

A RAG system's retrieval step is, underneath the marketing term, a
similarity search: "find the N chunks whose embeddings are closest to
this question's embedding." Similarity search has no innate concept of
"tenant" — it just ranks by vector distance. If a poisoned or merely
topically-similar document from another tenant happens to score high
enough, it gets pulled in, full stop, unless something upstream of
ranking
excluded it first.

Vulnerable retrieval flow

  question ──▶ embed ──▶ similarity search across ALL tenants' vectors
                                        │
                                        ▼
                          top-N chunks (tenant filter applied where? nowhere)
                                        │
                                        ▼
                                  handed to the LLM as context

Why this is worse than it looks

A tenant-filtering bug in a REST endpoint is usually visible in the API
response shape — you'd notice tenant_id: "tenant-b" showing up
somewhere it shouldn't. In RAG, the leak is laundered through natural
language: the model paraphrases or quotes the leaked chunk as part of a
fluent answer, so it can slip past reviewers who are only checking "does
the answer sound reasonable," not "did this answer just repeat another
customer's private document."

How you'll work through this lab

  1. Unlock the vulnerable-rag challenge.
  2. List its documents to understand what's in the corpus (without
    reading full content).
  3. Send varied questions as tenant-a until a tenant-b chunk shows up
    in retrieved_chunks.
  4. Confirm solved: true and inspect the leaked snippet.
  5. Read the official solution and explain why the fix belongs in the
    vector store, not the API layer.

Steps

Content exclusive to subscribers. See plans