

RAG Access Control: From Document Permissions to Leakage Testing
Author
Learn how to implement access control in RAG systems, focusing on retrieval filtering and leakage prevention.
Mapping Identity to Document Permissions
Before you can filter retrieval results, you need a permission model that connects each user to the documents and chunks they are allowed to see.
The most common starting point is role-based access control (RBAC), where users are assigned roles such as admin, editor, or viewer. Each role carries a set of permissions that define what actions a user can perform on a document—view, edit, delete, or share.
Once roles are defined, you assign document-level access control lists (ACLs). An ACL is a list of roles or individual users who have specific permissions on a document.
For example, a financial report might have an ACL that grants ‘view’ to the ‘finance’ role and ‘edit’ to the ‘admin’ role. This ACL becomes the source of truth for who can access that document.
Chunk-level inheritance is a critical design decision. In RAG, documents are split into smaller chunks for retrieval. To avoid duplicating permission logic, chunks should inherit the permissions of their parent document.
This means if a document is restricted to the ‘admin’ role, all its chunks are also restricted. Inheritance simplifies management and reduces the risk of misconfiguration.
For example, consider a document with an ACL that grants access only to the ‘admin’ role. When this document is chunked, each chunk carries a metadata tag indicating the document’s ACL.
During retrieval, only chunks with an ACL that includes the user’s role are considered. This ensures that a user without the ‘admin’ role never sees content from that document.
A common pitfall is relying solely on document-level permissions without considering chunk-level nuances. For instance, a document might contain sensitive paragraphs mixed with general content.
If you need finer-grained control, you can override inheritance at the chunk level, but this adds complexity. A practical approach is to start with document-level inheritance and only introduce chunk-level overrides when a clear business need exists.
Another consideration is how permissions are stored and updated. You can store ACLs in a separate permission service or embed them in document metadata. The choice affects retrieval performance and consistency.
A dedicated permission service allows centralized management and easier auditing, but it introduces a network dependency during retrieval. Embedding ACLs in metadata is faster but requires a synchronization mechanism when permissions change.
To implement this model, you need to define a clear mapping between identity and permissions. This mapping should be queryable at retrieval time.
For example, you might have a function that takes a user ID and returns a list of document IDs the user can access. This list can then be used to filter chunks.
Retrieval Filtering and Citation Control
Once you have a permission model, the next step is to apply it during retrieval. The goal is to ensure that search results and citations only include content the user is authorized to see. There are two main approaches: pre-filtering and post-filtering.
Pre-filtering involves restricting the search index before the retrieval step. For example, you can add a filter to the vector search query that only considers chunks whose metadata matches the user’s permissions.
This is efficient because it reduces the candidate set early. However, it requires that permissions are indexed and queryable.
Post-filtering retrieves a larger set of candidates and then filters them based on permissions. This is simpler to implement but can be inefficient and may expose sensitive content in intermediate steps.
In practice, a hybrid approach is often used: pre-filtering for coarse-grained restrictions and post-filtering for fine-grained checks.
Metadata tags or ACLs are used to filter chunks. For instance, each chunk might have a field `allowed_roles` that lists which roles can access it. During retrieval, you add a condition that the user’s role is in `allowed_roles`.
This can be done in the vector database query or in a separate filtering step.
Citation control is equally important. Even if retrieval is filtered, the generated answer might cite a document that the user cannot access. This can happen if the language model references a document ID that was not filtered.
To prevent this, you must verify that every citation in the generated answer points to a permitted document. This can be done by checking each citation against the user’s permissions before presenting the answer.
For example, suppose a user without access to document X asks a question that is answered using content from X. The retrieval filter should have excluded X’s chunks, so the model should not have used them.
However, if the model hallucinates a citation to X, the system must catch it. A simple check is to compare the citation’s document ID against the user’s allowed document list.
A practical implementation involves maintaining a mapping from chunk IDs to document IDs and their ACLs. After generation, you extract citations and verify each one.
If a citation is not allowed, you can either remove it or regenerate the answer without that source.
Another aspect is handling indirect leakage through paraphrasing. Even if a user cannot access a document, the model might generate an answer that paraphrases its content if the document was included in the training data.
This is a broader issue that cannot be fully solved by retrieval filtering alone. You should be aware of this limitation and consider additional safeguards, such as output filtering or differential privacy, if needed.
Testing Access Control: Allow, Deny, Revocation
To ensure your access control works, you need a systematic testing methodology. The core test cases are allow, deny, and revocation. Each test should verify both retrieval and citation behavior.
**Allow test:** An authorized user should be able to retrieve and cite content from documents they have permission to access.
For example, a user with the ‘viewer’ role on a document should see its chunks in search results and be able to cite them in generated answers.
**Deny test:** An unauthorized user should not be able to retrieve or cite content from documents they lack permission to access.
For example, a user without the ‘admin’ role should not see chunks from an admin-only document, and any generated answer should not cite that document.
**Revocation test:** After a user’s permission is removed, access should be immediately blocked. This means that if a user had access to a document and then their role is changed, they should no longer see its chunks or be able to cite it.
The test should verify that the change takes effect without delay.
**Cache invalidation test:** Cached results can leak information if they are not invalidated when permissions change.
For example, if a user’s search results are cached and then their permissions are revoked, the cached results might still contain restricted content.
You need to ensure that caches are invalidated or that cached results are re-checked against current permissions.
To implement these tests, you need a test environment with controlled data. Create a set of documents with different permission levels, and assign test users with specific roles.
Then, for each test case, perform a retrieval and generation request and assert that the results match expectations.
For example, to test denial, you might create a document with an ACL that only allows the ‘admin’ role. Then, as a ‘viewer’ user, you search for a query that would match that document.
The expected result is that no chunks from that document appear in the results, and any generated answer does not cite it.
Revocation testing requires a mechanism to change permissions dynamically. You might have an API to update a user’s role or a document’s ACL. After the change, you repeat the retrieval request and verify that the previously accessible content is now blocked.
Cache invalidation testing is often overlooked. If you use caching at any level—such as caching search results or generated answers—you must test that permission changes invalidate those caches.
One approach is to use a cache key that includes the user’s permission version. When permissions change, the version increments, and old cache entries become invalid.
A practical test suite might include the following cases:
– Allow: user with role ‘viewer’ can retrieve and cite a public document.
– Deny: user without role ‘admin’ cannot retrieve or cite an admin-only document.
– Revocation: after removing a user’s ‘viewer’ role, they cannot retrieve or cite a previously accessible document.
– Cache invalidation: after a permission change, a cached result for a user is not served if it contains now-restricted content.
These tests should be automated and run as part of your CI/CD pipeline to catch regressions.
Audit Fields and Logging
Use this checklist to guide your implementation and testing.
| Field | Description |
|——-|————-|
| Permission model definition | Define roles and permissions (e.g., RBAC). Specify document-level ACLs and chunk inheritance rules. |
| Retrieval filter implementation | Implement pre-filtering or post-filtering based on user permissions. Ensure citations are verified against permissions. |
| Test case list | Include allow, deny, revocation, and cache invalidation tests. Document expected outcomes for each. |
| Audit field checklist | Define audit fields to log access attempts, permission changes, and retrieval events for compliance. |
Multi-Tenancy and Data Isolation
Audit logging is the backbone of any access control system. Without detailed logs, you cannot prove who accessed what, when, and why. In a RAG context, audit logs must capture both retrieval events and permission changes.
A well-designed audit trail helps you detect anomalies, support compliance investigations, and debug access control failures.
### What to Log
For every retrieval request, log the following core fields:
– **User ID**: The unique identifier of the authenticated user or service account.
– **Document ID**: The identifier of each document returned by the retriever.
– **Action Type**: The operation performed, such as `retrieve`, `view`, or `download`.
– **Timestamp**: The exact time of the request, in UTC or with timezone offset.
Additionally, log the query text (or a hash of it) and the retrieval parameters (e.g., top-k, filters) to reconstruct the context. For permission changes, record:
– **Actor**: The user or admin who made the change.
– **Action**: `grant`, `revoke`, `update`, or `delete`.
– **Target**: The document or group affected.
– **Before/After Values**: The previous and new permission states.
### Making Logs Tamper-Proof
Logs are only useful if they cannot be silently altered. Implement append-only storage, such as a dedicated log service with restricted write access. Consider using cryptographic hashing to chain log entries, so any modification breaks the chain.
Regularly review logs for suspicious patterns, such as repeated denied access attempts or unusual retrieval times.
### Example Audit Fields
| Field | Example Value | Purpose |
|——-|—————|———|
| `user_id` | `user_123` | Identify the requester |
| `doc_id` | `doc_456` | Identify the accessed document |
| `action` | `retrieve` | Type of operation |
| `timestamp` | `2026-08-04T10:15:30Z` | When the event occurred |
| `query_hash` | `a1b2c3…` | Reconstruct the query |
| `permission_state` | `allowed` | Whether access was granted |
### Evidence Boundary
While general RAG overviews (e.g., EN1, EN4) mention security risks, they do not provide specific audit field guidance. The design above is based on standard security logging practices, not on a single source. Always adapt fields to your system’s requirements.
Common Pitfalls and Best Practices
In a multi-tenant RAG deployment, each tenant’s data must be strictly isolated. A tenant could be a company, department, or user group. Failure to isolate data can lead to cross-tenant leakage, which is both a security and compliance issue.
### Isolation Strategies
There are two primary approaches:
1. **Separate Storage**: Each tenant has its own vector database or index. This provides strong isolation but increases infrastructure cost.
2. **Shared Storage with Metadata Tags**: All documents are in one index, but each document is tagged with a tenant ID. Retrieval queries must include a mandatory tenant filter.
The second approach is more common due to cost efficiency. However, it requires rigorous enforcement to prevent accidental cross-tenant access.
### Implementing Tenant Filters
When using shared storage, ensure that every retrieval query includes a tenant filter. This filter should be applied at the database level, not just in the application code. For example, in a SQL-based vector store, add `WHERE tenant_id = ? ` to the query.
In a vector database, use metadata filtering to restrict the search space.
### Testing Isolation
To verify isolation, create test cases where Tenant A attempts to access Tenant B’s data. This includes:
– Direct document ID access
– Retrieval queries with keywords unique to Tenant B
– Attempts to bypass filters via prompt injection or API calls
Automate these tests in your CI/CD pipeline to catch regressions early.
General RAG sources (EN1, EN4) do not discuss multi-tenancy in depth. The strategies above are based on standard multi-tenant application design. Always validate with your own security testing.
Implementing access control in RAG is fraught with subtle mistakes. Here are common pitfalls and how to avoid them.
### Pitfall: Relying Solely on Prompt Engineering
Some developers try to prevent leakage by instructing the LLM to ignore unauthorized documents. This is unreliable because LLMs can be manipulated or may not consistently follow instructions.
Access control must be enforced at the retrieval layer, not left to the model.
### Best Practice: Enforce Permissions Both Before and After Retrieval
Apply permission checks twice:
1. **Pre-retrieval**: Filter documents based on the user’s permissions before sending them to the retriever.
2. **Post-retrieval**: After retrieval, re-check that the user is allowed to see each returned document. This catches cases where the retriever might return documents that bypassed the filter.
### Best Practice: Apply Least Privilege and Default Deny
Grant users the minimum permissions necessary for their role. By default, deny access to all documents unless explicitly allowed. This reduces the attack surface and limits the impact of a compromised account.
### Best Practice: Conduct Regular Security Audits and Penetration Testing
Access control is not a one-time implementation. Regularly audit your permission model, review logs, and run penetration tests to identify weaknesses. Use the results to refine your policies and filters.
### Required Artifact: RAG Access Control Checklist
Use the following checklist to guide your implementation and testing:
| Checklist Item | Status | Notes |
|—————-|——–|——-|
| **Permission Model Definition** | | |
| – Define user roles and document groups | | |
| – Map permissions to roles (e.g., read, write) | | |
| – Document the default deny policy | | |
| **Retrieval Filter Implementation** | | |
| – Add tenant filter to all retrieval queries | | |
| – Implement pre-retrieval permission filtering | | |
| – Implement post-retrieval permission checks | | |
| **Test Case List** | | |
| – Test allow access for authorized users | | |
| – Test deny access for unauthorized users | | |
| – Test permission revocation takes effect immediately | | |
| – Test cache invalidation after permission changes | | |
| – Test multi-tenant isolation (Tenant A vs. Tenant B) | | |
| **Audit Field Checklist** | | |
| – Log user ID, document ID, action, timestamp | | |
| – Log permission change actor and time | | |
| – Ensure logs are tamper-proof | | |
| – Regularly review logs for anomalies | | |
General RAG sources (EN1, EN4) do not provide specific best practices for access control. The recommendations above are based on standard security principles. Always test your implementation thoroughly.
Next step
Download the RAG Access Control Checklist to ensure your implementation covers all critical areas.
Related services and further reading
Official references and sources
Comments (0)
No comments yet. Be the first!