Multi-tenant RAG access control checklist: prevent cross-tenant data leaks (2026)
A practical access-control checklist for multi-tenant RAG. Derive tenant scope from the verified session, enforce it inside retrieval, preserve chunk-level ACLs, isolate caches, and test forbidden retrieval.
Table of Contents
- 1-minute summary
- Who this is for
- Conclusion
- Explanation
- Authentication is not document authorization
- Filter before similarity search, not after top-k
- Tenant isolation and document ACLs solve different problems
- Practical Guide
- Step 1: define the authorization contract
- Step 2: choose the isolation boundary by sensitivity
- Step 3: preserve ACL metadata during ingestion
- Step 4: build the scope in trusted application code
- Step 5: keep the scope through reranking and generation
- Step 6: isolate caches, traces, and derived data
- Step 7: add negative retrieval tests
- Step 8: monitor and rehearse failure handling
- Pitfalls
- Checklist
- FAQ
- 1. Is one namespace per tenant enough?
- 2. Can I use metadata filters in one shared index?
- 3. Why is post-retrieval filtering unsafe if I never show rejected chunks?
- 4. Should embeddings be treated as sensitive data?
- Sources
- Internal links
- Disclaimer
How do you prevent cross-tenant data leaks in a multi-tenant RAG system?
1-minute summary
- Derive the tenant and user scope from a verified server-side session. Never trust a
tenantId, namespace, or ACL supplied by the client. - Enforce authorization inside the vector or search query, before similarity scores, candidate results, reranking, or generation can cross the boundary.
- Preserve permissions at chunk level, isolate semantic caches and logs, fail closed on missing metadata, and test that forbidden documents are never retrieved.
Who this is for
- SaaS teams putting documents from multiple customers into one RAG platform
- Engineers adding vector search, hybrid search, reranking, or semantic caching to an existing authorization model
- Security and platform teams that need an auditable release gate for cross-tenant retrieval
Conclusion
Treat retrieval as an authorization boundary, not as a relevance feature that runs after authentication.
The safest flow is:
- authenticate the caller
- derive tenant, user, group, and role claims on the server
- choose an isolated index, collection, or namespace when the platform supports it
- apply document or chunk ACL filters inside the retrieval request
- rerank only authorized candidates
- verify the final context again and fail closed before generation
Post-retrieval filtering is not the primary control. By then, another tenant's vectors may already have influenced counts, timing, scores, candidate selection, logs, or a reranker. OWASP's 2026 guidance explicitly makes the embedding layer part of the application's trust boundary and recommends enforcing tenant scope inside the index query.
Use physical or namespace isolation for high-sensitivity tenants and trust zones. A shared index with metadata filters can be reasonable for lower-risk workloads, but only when every read and write path applies a server-derived scope and the system has negative tests for bypasses.
Explanation
Authentication is not document authorization
Authentication proves who called the application. It does not prove that every chunk returned by retrieval belongs to that caller.
A typical RAG request crosses several stores and transformations:
- source documents and their original ACLs
- extracted text and chunks
- embeddings and vector metadata
- keyword or vector candidates
- reranker input and output
- final prompt context and citations
- semantic cache, traces, and support logs
If one stage loses the tenant or ACL scope, the final answer can disclose content that the normal product UI would never show.
Filter before similarity search, not after top-k
This is unsafe:
search all tenants -> take top 20 -> remove unauthorized results -> send the remainder
The authorized tenant may receive poor or empty results because forbidden chunks occupied the top positions. More importantly, result counts, score distributions, latency, traces, or downstream components may reveal that other data exists.
The required order is:
verified authorization scope -> scoped search -> authorized candidates -> rerank -> final context
Azure AI Search documents tenant filters and document-level security filters as query-time controls. Pinecone recommends one namespace per tenant for serverless multitenancy, with every data-plane operation targeting one namespace. Other engines use tenant partitions, collections, shards, or prefilters. The product names differ; the security property is the same: unauthorized vectors must not enter the candidate set.
Tenant isolation and document ACLs solve different problems
A tenant boundary answers, “Which customer owns this data?” An ACL answers, “Which people or groups inside that customer may read this chunk?”
One namespace per tenant is not enough when a tenant contains private HR, legal, finance, or project data. Keep both layers when the source system has finer permissions:
- tenant or trust-zone isolation
- document- or chunk-level users, groups, roles, or classification labels
Apply permissions at chunk level when one source document mixes public and confidential sections. Missing or stale ACL metadata must deny retrieval, not silently make a chunk public.
Practical Guide
Step 1: define the authorization contract
Write down the attributes that determine access before choosing a vector database:
tenant_idor organization boundary- authenticated
user_id - effective group and role IDs
- project, region, or classification scope
- ACL version or last-synchronized timestamp
Derive these values from a verified session or trusted identity provider. Do not copy them from request JSON, query parameters, model output, or retrieved text.
Step 2: choose the isolation boundary by sensitivity
Use a practical hierarchy:
- Dedicated service or index: regulated, contractually isolated, or unusually sensitive tenants
- Namespace, tenant partition, or collection: normal SaaS tenant isolation with shared infrastructure
- Shared index plus server-enforced metadata filters: lower-risk shared data or cases that genuinely require cross-tenant search
Do not mix external web content, internal documents, and restricted customer data in one trust zone merely because their embedding dimensions match.
Step 3: preserve ACL metadata during ingestion
Every chunk should retain enough metadata to reproduce the source authorization decision:
{
"chunk_id": "refund-policy#annual-plans-02",
"tenant_id": "tenant_7",
"source_id": "refund-policy",
"allowed_group_ids": ["billing", "support-leads"],
"classification": "internal",
"acl_version": "2026-09-05T02:10:00Z"
}
Ingestion must validate that required scope fields exist. Quarantine records with missing or malformed authorization metadata. When source permissions change, update or reindex the affected chunks within a defined service-level objective.
Step 4: build the scope in trusted application code
Keep the retrieval function narrow. The following TypeScript is vendor-neutral pseudocode; adapt the filter syntax to your search engine.
type AuthzContext = {
tenantId: string;
userId: string;
groupIds: string[];
};
async function retrieve(query: string, sessionToken: string) {
const authz: AuthzContext = await authzFromVerifiedSession(sessionToken);
const results = await vectorStore.query({
namespace: `tenant:${authz.tenantId}`,
query,
topK: 12,
filter: {
tenant_id: authz.tenantId,
allowed_group_ids: { anyOf: authz.groupIds },
},
});
if (results.some((r) => !isAuthorized(r.metadata, authz))) {
throw new Error('retrieval_scope_violation');
}
return results;
}
The final check is defense in depth and an alerting point. It does not justify searching a global candidate set first.
Step 5: keep the scope through reranking and generation
Only authorized candidates may enter the reranker. Validate the final chunk IDs before building the prompt, and only render citations the caller may open.
Do not ask the LLM whether a document is allowed. Prompts such as “Only use documents for this tenant” are behavioral instructions, not authorization controls.
Step 6: isolate caches, traces, and derived data
Authorization can fail after correct retrieval if derived systems ignore scope.
- include tenant and authorization-scope version in semantic-cache keys
- never reuse a generated answer across tenants unless its source set is explicitly public
- restrict trace, eval, and support-tool access to the same or stronger boundary
- treat embeddings and vector backups at the source document's sensitivity level
- delete derived chunks, vectors, and cache entries when the source is deleted
Avoid returning raw similarity scores to untrusted clients. They can create an oracle for probing whether specific content exists.
Step 7: add negative retrieval tests
Create fixtures for at least two tenants and two permission groups. For each query, record both expected and forbidden chunk IDs.
Release gates should include:
- zero forbidden IDs in candidate retrieval
- zero forbidden IDs after reranking and context assembly
- no cache hit across incompatible scopes
- deny-by-default behavior for missing tenant or ACL metadata
- permission revocation reflected within the documented freshness window
- consistent behavior for direct IDs, paraphrases, and adversarial probe queries
Run the tests against the same API path production uses. Unit-testing only a filter-builder does not catch an unscoped fallback query.
Step 8: monitor and rehearse failure handling
Log tenant scope, principal or group identifiers, index version, returned chunk IDs, and policy outcome. Redact or hash queries when they can contain sensitive text, according to your retention policy.
Alert on:
- any returned chunk with a mismatched tenant or ACL
- requests missing a scope
- repeated denied or cross-tenant probe patterns
- unusual access to embedding or similarity-search APIs
- ACL synchronization lag beyond the agreed window
If a vector store or embedding backup leaks, do not assume “only vectors” means low impact. Escalate it through the same incident process used for sensitive source data.
Pitfalls
- trusting
tenantId, namespace, group IDs, or filter JSON from the browser - authenticating the search API but not authorizing each retrieved chunk
- filtering after global top-k retrieval
- applying tenant scope to vector search but forgetting keyword search or fallback search
- reranking authorized and unauthorized candidates together
- using one tenant namespace while ignoring document-level ACLs inside that tenant
- treating missing ACL metadata as public
- copying answers between tenants through a shared semantic cache
- leaving deleted or permission-revoked content in vectors, backups, or caches
- exposing raw similarity scores, counts, or verbose traces to clients
- testing only successful retrieval and never asserting forbidden IDs
- relying on a system prompt to enforce data access
Checklist
- [ ] Tenant scope comes from a verified server-side session
- [ ] Client-supplied tenant, namespace, and ACL values are ignored for authorization
- [ ] Every ingestion path writes required tenant and ACL metadata
- [ ] Missing or invalid authorization metadata fails closed
- [ ] High-sensitivity tenants or trust zones use hard isolation
- [ ] Tenant scope is enforced inside every vector, keyword, hybrid, and fallback query
- [ ] Document or chunk ACLs are enforced in addition to tenant isolation
- [ ] Rerankers receive authorized candidates only
- [ ] Final context and citations are checked before generation
- [ ] Semantic-cache keys include tenant and authorization scope
- [ ] Traces, eval datasets, exports, and support tools preserve the same boundary
- [ ] Embeddings and backups are classified like source documents
- [ ] Source deletion removes chunks, vectors, cache entries, and derived artifacts
- [ ] Permission changes propagate within a defined freshness window
- [ ] Retrieval logs contain enough IDs and policy data for an audit
- [ ] Raw similarity scores are not exposed to untrusted clients
- [ ] Tests include at least two tenants and multiple permission groups
- [ ] Forbidden retrieval is a zero-tolerance release metric
- [ ] Tests cover direct, paraphrased, and adversarial probe queries
- [ ] Incident response treats cross-tenant vector exposure as a data-security event
FAQ
1. Is one namespace per tenant enough?
It is a strong tenant boundary when the vector platform provides real namespace isolation, but it does not replace permissions inside a tenant. If users have different access to HR, legal, finance, or project documents, enforce those ACLs at document or chunk level too.
2. Can I use metadata filters in one shared index?
Yes, when the risk and platform behavior justify it. The filter must be mandatory, built from server-verified identity, and applied inside the retrieval operation. Add fail-closed defaults and negative tests. For high-sensitivity workloads, prefer a harder isolation boundary.
3. Why is post-retrieval filtering unsafe if I never show rejected chunks?
Unauthorized vectors can still affect top-k selection, result counts, scores, timing, reranking, traces, and cache behavior. The authorized tenant can also lose relevant results because forbidden chunks occupied the candidate set.
4. Should embeddings be treated as sensitive data?
Yes. Current OWASP guidance treats the embedding layer as part of the trust boundary and warns that embeddings and backups can expose information about source documents. Apply equivalent access, encryption, retention, and incident controls.
Sources
- OWASP GenAI LLM Top 10 2026
- Design a secure multitenant RAG inferencing solution (Microsoft Azure Architecture Center)
- Document-level access control in Azure AI Search
- Design patterns for multitenant SaaS applications and Azure AI Search
- Implement multitenancy with namespaces (Pinecone Docs)
Internal links
- Parent hub: AI development
- Related:
Disclaimer
General engineering and security guidance only. Validate the isolation design against your vector platform, identity system, data classification, contracts, and regulatory obligations.
Popular
- 1Permit2 explained (Web3): why approvals changed and how to use it safely (checklist)
- 2Read wallet signing screens (Web3): a 30-second checklist to avoid permission traps
- 3Spec-to-implementation prompt template (AI development): how to stop the model from guessing
- 4Revoke token approvals on EVM: how to audit allowances safely (checklist)
- 5Clarifying questions checklist (AI development): what to ask before you let an LLM build