What is permission-aware retrieval and why does it matter?
An enterprise RAG system pulls files from shared drives, support tickets, wiki pages and contract archives into one search index. In the source systems, every document has an access control list (ACL) that says who may read it. If that list is lost during ingestion, the index becomes a single pool where everyone can reach everything. A user can ask a question that sits entirely within their own permissions, and retrieval will still return the semantically closest passage, which may be a salary table meant only for managers.
Permission-aware retrieval means search returns only passages the person asking is allowed to read in the source system. The risk is not limited to a citation in the answer: once the model sees a restricted passage in its context, it can summarise it, paraphrase it or use it in the next tool call. OWASP's 2025 list of risks for large language model applications treats this as its own category: its vector and embedding weaknesses entry includes one group's documents being retrieved for another group's query and context leaking across tenants. The same entry notes that significant parts of the source text can be recovered from embedding vectors, so the vector store needs at least the same protection as the document store.
Where should permissions be enforced?
There are four places to enforce permissions, and they do not give the same guarantee. The most common mistake is leaving the check to the very end, as an instruction to the model.
| Method | When it fits | Watch out for |
|---|---|---|
| Security filter at query time | The default for most enterprise RAG | Every passage needs a current permission field |
| Separate index per tenant or group | A small number of strictly separated customers or units | Cost and maintenance grow with the number of groups |
| Checking results against the source system | Permissions change very often and extra latency is acceptable | Latency and API limits; use with a filter, not alone |
| Dropping results after search, before the model | A stopgap until a filter is in place | Answer quality falls as results are removed |
| Telling the model not to use restricted content | Never on its own | The model has already seen the restricted text |
We recommend enforcing permissions in the search itself, as a filter, before ranking and generation. Microsoft describes this for Azure AI Search as the security filter pattern: each document has a field holding the permitted group IDs, and the query adds a filter on that field with the user's groups. In Elasticsearch, the same job is done with document-level security, a query written into the role definition that can reference the signed-in user through a template.
What permission data belongs in the index?
For the filter to work, store at least these fields with every passage:
- Source document ID: Which document and which version the passage came from.
- Tenant: In a multi-customer product, the customer the passage belongs to; a mandatory filter on every query.
- Permitted users and groups: Stable identifiers rather than values that can change, such as email addresses. Azure AI Search's document-level access feature also asks for Microsoft Entra object IDs in its user and group fields.
- Where the permission comes from: Inherited from a folder, granted on the document, or opened through a sharing link.
- Sync time and ACL version: So you can measure how stale this information is.
- Sensitivity label: Classes such as "confidential" or "contains personal data", if you have them.
Check how mature the built-in options are, too. At the time this article was updated, Azure AI Search's document-level access features (ADLS Gen2 ACLs, SharePoint permissions, Microsoft Purview sensitivity labels) are still in preview. Preview features are not covered by a service-level agreement and Microsoft does not recommend them for production workloads. According to the same page, attribute-based (ABAC) conditions in ADLS Gen2 are not evaluated, and permission changes take some time to reach search. Whichever route you choose, test its behaviour with your own data before going to production.
Inheritance, exceptions and revocation
Write down a rule for how folder permissions, sharing links, document-level exceptions and group membership carry over to passages. A file can override its folder's rule, in which case a group label inherited only from the folder is wrong. Nested groups are often missed as well: a user may be authorised not directly but through a subgroup.
Set a target time for revocation and measure it. For example, when an employee is removed from the HR group, you might aim for payroll documents to disappear from search within 15 minutes. What matters is not the number itself but that it matches expectations in the source system and is monitored. Raise an alert when sync falls behind; hiding documents whose ACL data is older than the agreed limit is safer than showing them to the wrong person.
Example: the payroll query test
An employee asks, "How is this year's pay rise calculated?" The index holds two documents: the public pay policy and a managers-only table with individual rise percentages. The table may be semantically closer to the question. Ask the same question under three identities and check the raw search results, the list of passages before anything reaches the model:
| Identity | Should see | Should not see |
|---|---|---|
| Employee | Pay policy | Rise table |
| HR specialist | Policy and table | Another tenant's documents |
| Specialist just removed from HR | Pay policy | Rise table (after the target time) |
Inspect the raw result IDs and passages, not only the final answer. The model may have seen the restricted passage and still written a harmless answer; that does not mean the test passed.
A leakage test plan
Automate the following tests and run them after every connector, group sync or index change:
- Ask the same question under identities with different permissions and compare the raw results.
- Remove a user from a group and repeat the test once the target time has passed.
- Create documents with the same name for two tenants; no result may cross between them.
- Ask for the restricted information indirectly rather than by name ("last year's rise range for managers").
- Check how files shared by link, or shared outside the company, are indexed.
- Add a document with missing ACL data; search must never return it.
- Test cached answers under different identities.
- Open the citation link in an answer as an unauthorised user; the source system must deny access.
Separate the ingestion pipeline and identities
Connectors may need broad read access to fetch source files; that access must never pass to the user running the query. Use separate service identities for ingestion and for queries, and record where every passage came from. OWASP's AI agent security cheat sheet stresses least privilege and treating retrieved content as untrusted data. The same principle makes it harder for a malicious document to steer later tool calls.
Caching, citations and logs
An answer cache cuts cost but can easily break the permission boundary: an answer generated for a manager's question can be served from cache to an employee who asks the same thing. Add the tenant and the user's permission set to the cache key, or switch caching off for permission-sensitive queries. Citation links must go through the source system's own access check. In the audit log, keep the user ID, the filter applied, the returned document IDs, the ACL version and the time, without storing sensitive text you don't need. If permissions cannot be evaluated, return a safe error instead of widening the search.
Common mistakes
- Hiding restricted results only in the interface, not enforcing permissions in search.
- Ingesting permissions once and never syncing group changes.
- Using values that can change, such as email addresses, as identifiers.
- Testing only the final answer and never looking at the raw results.
- Leaving caches and summary indexes outside the permission model.
How Hatson Tech builds this
Permission filters applied at retrieval time are a basic requirement in our RAG and semantic search solutions. We start a project by mapping the permission model of the source systems and write the test plan above into the acceptance criteria. Where data cannot leave the organisation, see our guide to in-house AI; to improve search quality, see our article on hybrid search and reranking. Before applying this approach, check the sources against your own data, permissions and the product versions you use.