Lesson 3 of 6 · 9 min read
RAG Security
In this lesson
TL;DR: A RAG system copies documents into the model's context on demand, so it must enforce the same access rules as the systems it copied from. Copy permissions into chunk metadata at ingestion, filter retrieval on the asking user's identity before ranking, isolate tenants, keep permissions and deletions in sync, and never rely on the model to withhold what it was given. Then treat every retrieved chunk as untrusted input (its author can inject), and handle the answer like any other model output.
Before you read
Pick an answer before you read further. The lesson below explains it, and guessing first, right or wrong, helps the explanation stay with you.
1Retrieval returns the top 20 chunks by similarity, then the application removes chunks the user may not see. Is that correct?
What you should be able to do
Trace one document from its source through chunks, embeddings, retrieval, reranking and a generated answer. Identify the last trusted permission check before each recipient sees its text. Explain how a permission change invalidates an already cached answer. If the pipeline is unfamiliar, first read how LLM applications work.
Three properties a secure RAG system needs
1. Retrieval enforces authorization. The model will use whatever is in its context. If a chunk the user may not read reaches the prompt, the only remaining defence is the model's discretion, which is not a defence. Enforce the decision inside the trusted retrieval service before any disallowed text reaches the caller, model or an unauthorized downstream processor.
2. Retrieved content is untrusted. Any document someone can write is a channel for indirect prompt injection and for misinformation. Internal does not mean trusted.
3. The answer is handled safely. It may quote retrieved text verbatim, include links, or be rendered as markdown; standard output handling applies.
Getting authorization right
Source system
Has its own ACLs
Ingestion
Copies ACLs to metadata
Index
Per tenant
Retrieve
Filter by user, then rank
Model
Also in the picture
User
- Authenticated
Permissions travel with the data
Each chunk carries the source document's access list and tenant, copied at ingestion.
At ingestion: record, for every chunk, the source document ID, tenant, and the principals (users, groups) allowed to read it. Strip or restrict documents whose permissions cannot be represented.
At query time: filter by tenant and by the user's principals inside the search, so ranking only considers allowed chunks. For high-sensitivity data, re-check permissions against the source system for the final set of chunks.
Over time: propagate permission changes and deletions with a defined maximum lag, and test revocation. Cache scope must reflect the caller's actual access, not just the tenant. Include an authorization version or invalidate affected entries when access changes, and authorize the source documents again before serving a sensitive cached answer.
Isolation: enforce tenant scope in a mandatory retrieval boundary. Engine-level policies, separate credentials or separate indexes can reduce the chance that an omitted application filter exposes another tenant. Separate indexes on shared infrastructure are logical separation, not automatically separate compute or administrative access.
Worked example: post-filtering and retrieval quality
A corpus holds 2,000,000 chunks. Priya, through three groups, may read 40,000 of them: 2%.
- Post-filter. Retrieve the top 10 from the whole corpus, then drop what Priya may not see. If relevance is unrelated to permission, the expected number of allowed results is 10 × 0.02 = 0.2 per query: most answers come back empty. Increasing the candidate count to 500 gives an expectation of 10 allowed results under the same simplifying assumption, at extra cost. This is illustrative arithmetic, not a measured production result. Filtering inside a trusted retrieval service can preserve confidentiality if disallowed chunks never reach the model, an unauthorized reranker, logs or the caller; the concern here is recall and the pressure to weaken policy.
- Pre-filter in the index. Pass Priya's principals (her user ID and three groups) and the tenant as a filter inside the approximate nearest-neighbour search, so the top 10 are drawn only from documents she may read. Test retrieval quality under a 2% filter on your engine, because filtered approximate search behaves differently across vector databases. Azure AI Search documents the filter pattern and explicitly distinguishes a filter string from authenticating the caller.
- Chunking. The permission on the parent PDF must be copied to every chunk. Microsoft's Azure AI Search documentation warns that without this projection, chunk-level references are not filtered.
- Revocation. Priya leaves group g2 at 09:00. If the indexer that syncs permissions runs every six hours, she can retrieve g2's documents until 15:00. Shorten the sync for sensitive sources, or, for the most sensitive tier, re-check final results against the source system's ACL at answer time.
- Caches. Include tenant, effective access scope, authorization version and relevant corpus/model versions. A group-membership hash alone does not reflect a changed document ACL. Keep source IDs with cached answers so a cache hit can be checked against current permission and deletion state.
Filter after retrieval
Top 10 from 2,000,000 chunks
Drop what Priya cannot read
expect 0.2 left
Empty answers, filter loosened
Outcome, unsafe: Fails users, then fails security
Pressure to raise k or switch the filter off.
Filter inside the index
Principals and tenant as a filter
Top 10 from her 40,000 chunks
ACL copied to every chunk
Answer from permitted text only
Outcome, safe: Relevant and authorised
Revocation lag still depends on sync frequency.
Post-filtering
When a user can read 2% of the corpus, filtering the top 10 leaves almost nothing, so the filter gets weakened.
Isolation options by engine
Vector stores offer different isolation primitives, and the choice trades isolation strength against cost. Weaviate's multi-tenancy stores each tenant on a separate shard and requires the tenant name on every operation. PostgreSQL with pgvector can use row-level security, with the caveat from the broken access control lesson: superusers, roles with BYPASSRLS and, unless FORCE ROW LEVEL SECURITY is set, the table owner bypass it, so a retrieval service connecting as the owner silently ignores every policy. Azure AI Search offers string-match security filters that the application passes, and newer modes that take the user's Entra token and trim results using synchronised permission metadata. Choose the boundary that matches the threat: an engine policy, an unavoidable retrieval service, separate credentials, or dedicated infrastructure. Test that no caller can skip tenant and document checks, including through administrative and batch interfaces.
Treating retrieved text as untrusted
- Know who can write each source. A wiki every employee can edit is an injection channel for any compromised account.
- Mark retrieved text as data in the prompt and use a model trained with an instruction hierarchy. This lowers, not removes, injection risk.
- Limit what a RAG answer can trigger. A bot without tools still produces text that can disclose confidential context or mislead a user. Keep unauthorized documents out of its context, constrain rendering and cite sources; removing tools reduces available actions but does not remove disclosure risk.
- Watch for poisoning: documents designed to rank highly for specific queries and carry instructions or false claims. Review changes to high-traffic sources and monitor for documents that suddenly dominate retrieval.
Poisoning: five documents in millions
PoisonedRAG (Zou and colleagues, USENIX Security 2025) showed how little an attacker needs. Five crafted texts per target question achieved about 90% attack success against knowledge bases of 2.7 to 8.8 million passages. An attack must satisfy two conditions, and they are worth testing separately: the poisoned text must be retrieved into the top results for the target question, and the model must generate the attacker's answer from it. The defences the authors tested did not hold: paraphrasing the query lowered success only modestly, perplexity-based detection produced too many false positives, removing duplicates did nothing because the poisoned texts differed, and retrieving many more passages still left 41% to 43% success. The controls that matter are about who can write to the corpus: write permissions on sources, provenance and trust weighting kept separate from similarity scores, monitoring for documents that suddenly dominate retrieval for high-value queries, and canary queries on sensitive topics.
Embeddings are sensitive data
Vectors look like opaque numbers, so teams store them with less care than the text. Morris and colleagues ("Text Embeddings Reveal (Almost) As Much As Text", EMNLP 2023) recovered 92% of 32-token inputs exactly from their embeddings with an iterative correct-and-re-embed method, and recovered full names from clinical notes. The 92% result applies to the paper's tested models and short inputs, not every embedding system. It is still enough to reject the claim that vectors are anonymized: encrypt it, restrict access to it, include it in data-deletion workflows and breach assessments, and do not share embeddings with third parties you would not share the text with.
Common RAG failures
| Failure | Result |
|---|---|
| Whole drive indexed without ACLs | Every user can retrieve restricted documents |
| Filtering after top-k ranking | Pressure to loosen filters; relevance collapses |
| Permissions synced only at first ingestion | Revoked users keep access through the assistant |
| Deletions not propagated | Deleted data keeps appearing in answers |
| Shared response cache | One user's answer, built from their data, served to another |
| Optional tenant filter that callers can omit | An unfiltered path can expose other tenants |
Exercise: revoke access without changing the question
Use a local fixture with two tenants and three short documents: one public, one private to each tenant. Give the retrieval service an authenticated principal from trusted server state. The client supplies the search question, never its own tenant permission filter.
| Step | Evidence to inspect | Expected result |
|---|---|---|
| Search as the first tenant | Candidate IDs and final model input | The other tenant's private text never enters the model input |
| Repeat the exact query as the second tenant | Cache lookup and returned source IDs | A cached answer from the first tenant is not reused across the boundary |
| Revoke the first tenant's private document permission | Source ACL version, index metadata and cache state | New requests stop returning that document under the stated revocation policy |
| Make the permission service unavailable | Decision log and returned response | The private source is denied or the request fails; the filter is not silently removed |
If revocation propagates asynchronously, name the maximum delay your design promises and test that delay. Immediate revocation requires a current authorization check or an equivalent invalidation mechanism. A visible citation alone does not prove that the caller may read its source.
This exercise tests confidentiality and permission freshness. A separate evaluation is needed for whether the answer is accurate and supported by its permitted sources. Run fixtures only in systems you own or are authorised to test.
Misconceptions interviewers listen for
- "The model will respect an instruction not to reveal restricted documents." It has already been given the text; authorisation must happen before retrieval.
- "Embeddings are anonymised." Research has recovered sensitive text in tested settings; recovery depends on the model, input and attacker access.
- "Deduplication stops poisoning." Poisoned texts can all differ.
- "Separate indexes per tenant remove the need for authorisation." Users within a tenant still have different permissions.
- "Permissions are checked at ingestion." They change after ingestion; sync lag is an exposure window.
What if · interview follow-ups
Hold your answer as the constraints change
You are reviewing an enterprise RAG assistant over SharePoint, a wiki and support tickets for several business units sharing one vector index. The interviewer changes one detail at a time.
Start here
What if permissions are checked by filtering the top 10 results after retrieval?
What fraction of the corpus can a typical user read?
If a user can read a small fraction, most top results are forbidden and answers come back empty, which leads to raising k or disabling the filter. Copy each document's permissions to every chunk and filter inside the index on the caller's principals and tenant, then test retrieval quality under that filter.
Carry it forwardAuthorise inside retrieval, before ranking, not after.
Weak answerDefending post-filtering because it 'never returns forbidden text'.
Constraint changes
What if an employee leaves a group but can still retrieve its documents for hours?
When does the index learn about the change?
Only at the next permission sync, so the sync interval is an exposure window. Shorten it for sensitive sources, trigger syncs on group changes, and for the most sensitive tier re-check results against the source system's live ACL before answering.
Carry it forwardPermission changes propagate on a schedule; size the schedule to the data's sensitivity.
Weak answerAssuming revocation in the source system is instant in the index.
Constraint changes
What if the retrieval service connects to PostgreSQL as the table owner and relies on row-level security?
Who bypasses RLS?
The table owner bypasses policies unless FORCE ROW LEVEL SECURITY is set, and superusers and BYPASSRLS roles always do, so the policy silently does nothing. Connect as a separate non-owner role, set the tenant and principals per request, and test with a query that omits the filter.
Carry it forwardCheck which role the application uses before trusting a database-level control.
Weak answerTrusting RLS because it is enabled on the table.
Constraint changes
What if someone plants five wiki pages to steer answers about the refund policy?
Which two things must the pages achieve?
They must be retrieved for the target questions and then followed, which PoisonedRAG achieved about 90% of the time with five texts. Restrict who can edit sources used for policy answers, weight provenance separately from similarity, alert when new documents dominate retrieval for high-value queries, and run canary questions on those topics.
Carry it forwardRAG poisoning is a write-access problem first; control who can author what the model retrieves.
Weak answerRelying on deduplication or perplexity filters.
Constraint changes
What if the vector database leaks, and the vendor says it only held embeddings?
Can text be recovered from embeddings?
Yes: published inversion methods recover most short passages exactly, so treat it as a breach of the underlying text. Assess which documents were embedded, notify accordingly, and in future encrypt the store, restrict access and include vectors in deletion workflows.
Carry it forwardEmbeddings are a representation of the data, with the data's sensitivity.
Weak answerTreating the leaked vectors as anonymous.
Now defend it
As the defender, how would you continuously prove the RAG system respects permissions?
Plant canary documents per tenant and permission group, query as users who should and should not see them on every release, measure revocation lag with timed tests, monitor retrieval for documents that suddenly dominate sensitive queries, and log which documents fed each answer with the caller's principals.
Primary references
References for the mechanisms discussed above, accessed 6 November 2026:
- OWASP authorization: validate permissions on every request.
- PoisonedRAG, USENIX Security 2025: experimental setting and results.
- Text Embeddings Reveal (Almost) As Much As Text, EMNLP 2023.
How this shows up in interviews
"Secure a RAG application end to end" and "enforce document-level permissions in RAG" are two of the most common AI application security questions. Lead with authorization at retrieval, because a permission error can expose documents without any model manipulation, then cover untrusted content, output handling, and operations (sync, deletion, caching, monitoring).
Say it in 30 seconds: "RAG copies data into the model's context, so retrieval has to enforce the same permissions as the source: copy ACLs and tenant into chunk metadata, filter on the asking user's identity before ranking, isolate tenants, and sync permission changes and deletions. Never rely on the model to withhold what it was given. Then treat retrieved text as untrusted because its authors can inject, and handle the answer like any model output."
Check yourself
Say or write your answer first, then reveal. Explaining it from memory, in your own words, is the skill an interviewer is checking.
1A contractor's access to a client folder is removed on Monday. On Wednesday the internal assistant still answers their questions with that client's documents. What went wrong, and what is the fix?
2A user can read 2% of a corpus. If you retrieve the top 10 and then filter, how many results do you expect to keep?
3Why should embeddings be treated as sensitive data?