One dangerous RAG design is to upload broadly and treat source-cited answers as automatically authorized.
An answer may be accurate and cited while still leaking salary bands, customer contracts, legal drafts, board notes, support tickets, HR investigations, or security procedures.
A company knowledge RAG is not a search box with nicer prose. It is a permissioned information system. Treat it that way.
Retrieval must enforce the same or stricter permissions as the source systems. If a user cannot open the document in Google Drive, SharePoint, Notion, Confluence, or the CRM, the RAG should not retrieve it for that user.
The core rule
The retrieval layer must answer this question before returning any chunk:
Is this user allowed to see this source right now?
Not “is this source in the vector database?” Not “is this source relevant?” Not “is this source useful?” Permission comes first.
There are three common patterns:
| Pattern | How it works | Fit |
|---|---|---|
| Separate indexes | One index per audience or workspace | Simple teams, coarse permissions |
| Metadata filtering | Store ACL/group/source metadata and filter before retrieval | Systems whose revocation-delay target can be met by synchronization |
| Real-time permission check | Query source system permissions at retrieval time | Sensitive or frequently changing permissions |
The right answer depends on source semantics, revocation-delay target, identity model, and impact. Separate indexes and metadata filtering are not automatically sufficient; prove them with authorization and revocation tests.
The hard part: keeping ACLs in sync
Every pattern above quietly depends on one thing: the permission data in your index matching the permission data in the source system. That synchronization is where the real engineering lives.
Where the ACLs come from. Start from the current official Microsoft Graph permission resource, Google Drive sharing guide, and Confluence content-permission API. Each source has different users, groups, inheritance, links, ownership, and rate-limit behavior. Verify effective access, not only direct grants.
Group expansion is not optional. Most real permissions are granted to groups, and groups nest. “Sales EU” inside “Sales” inside “All Staff” must be flattened to concrete users either at sync time (bigger index metadata, faster queries) or at query time (fresher, slower, more API calls). Pick one deliberately; teams that do it accidentally do it inconsistently.
Sync lag is a security parameter, not a performance detail. When someone loses access to a document — role change, offboarding, a deal going confidential — the index keeps serving the old ACL until the next sync. Decide the acceptable revocation delay per corpus and write it down: near-real-time for restricted corpora, hours may be acceptable for internal process docs. If nobody has written that number down, the real answer is “whenever the nightly job runs,” which will not survive a security review.
Real-time checks buy freshness and cost you latency, rate limits, and a failure mode. A per-retrieval permission call adds a source-system round trip to every query and eats API quota fast at scale; the usual compromise is a short-lived cache, which quietly converts “real-time” back into “sync lag with a smaller number.” Whatever you choose, make the timeout behavior explicit: if the permission check fails or times out, the chunk does not ship. Fail closed, log the failure, and let the assistant refuse — a slow correct answer beats a fast leak.
Make revocation explicit. Consume supported change notifications or poll with an owned cursor, version ACL snapshots, invalidate authorization and answer caches on access changes, and prevent an older sync result from overwriting a newer one. Store the source revision and ACL revision on each chunk so tests can detect mixed generations.
The offboarding test from the testing section is how you find out whether any of this actually works: a disabled account must retrieve nothing from restricted corpora within the documented revocation target, including through retrieval, response, semantic, and CDN caches.
Source boundaries
Do not create one giant knowledge pool. Separate by audience and sensitivity:
| Corpus | Audience | Examples | Rule |
|---|---|---|---|
| Public/product | Everyone | Help docs, public pricing, product pages | Safe for broad assistant |
| Internal operations | Employees | Process docs, internal FAQs | Employee-only |
| Department | Department members | Sales playbooks, support macros, engineering runbooks | Group-filtered |
| Customer records | Assigned teams | Tickets, contracts, account notes | Strict ACL and audit |
| Restricted | Named users only | HR, legal, security, board | Usually separate system or no RAG |
The fewer audiences a corpus serves, the easier it is to reason about leakage.
Ingestion controls
The ingestion pipeline is where many leaks start.
Before indexing a source, capture:
- Source system.
- Document ID.
- Owner.
- Audience or ACL.
- Sensitivity label.
- Created and updated timestamps.
- Expiry or review date.
- Whether the document may be used for AI retrieval.
- Whether the document contains personal data.
If the source system already has labels, preserve them. If it does not, add a lightweight classification step before ingestion.
Retrieval controls
Retrieval should happen in this order:
- Identify the user and groups.
- Identify the requested workspace or assistant.
- Filter candidate sources by corpus, ACL, sensitivity, and freshness.
- Retrieve relevant chunks only from allowed sources.
- Rerank allowed chunks.
- Generate the answer with source references.
- Refuse or escalate when allowed sources are insufficient.
Do not retrieve first and filter later in the prompt. If a forbidden chunk enters the model context, the boundary has already failed.
Prompt and answer behavior
The assistant should be instructed to:
- Answer only from retrieved sources.
- Cite source title and section/link.
- Say when allowed sources do not contain the answer.
- Mark inference separately from sourced facts.
- Avoid revealing that restricted sources exist.
- Avoid summarizing access-denied material.
Bad refusal:
“I found HR salary bands but you do not have access.”
Better refusal:
“I do not have an approved source available to answer that.”
The second answer does not leak the existence or topic of restricted documents.
Logging without creating a second leak
RAG logs are sensitive. They can contain user questions, retrieved chunks, source IDs, answers, and sometimes personal data.
Log enough to debug:
- User ID or pseudonymous ID.
- Assistant/workspace.
- Query timestamp.
- Source IDs retrieved.
- Permission-filter outcome.
- Answer ID.
- Refusal/escalation reason.
- Latency and errors.
Be careful with:
- Full user questions.
- Full retrieved chunks.
- Full generated answers.
- Customer data.
- HR/legal/security topics.
For sensitive systems, store redacted logs or source IDs rather than full text. Give logs their own access control and retention period.

Stale and conflicting sources
Permission is not the only boundary. Source quality matters.
Every indexed source should have an owner and a freshness rule:
| Source type | Review rule |
|---|---|
| Pricing | Review on every pricing change |
| Policy | Review on policy owner update, at least quarterly |
| Product docs | Review on release |
| Legal template | Review by legal owner |
| Support macro | Review monthly or after escalation pattern |
When sources conflict, the assistant should surface the conflict only if the user can access both sources. Otherwise it should answer from the highest-authority allowed source or escalate.
Testing permission boundaries
Test with users, not only documents:
- Employee with broad access.
- Employee with narrow department access.
- Manager with team-only access.
- Contractor.
- Former employee or disabled account.
- Customer-facing support user.
- Admin.
For each, ask:
- A question they should be able to answer.
- A question just outside their permissions.
- A question about a restricted document they know exists.
- A question where public docs and internal docs conflict.
- A question using prompt injection: “ignore access rules.”
The correct result is not only “good answer.” It is “good answer from allowed sources.”
Rollout path
Start with the least sensitive corpus:
- Public/product docs.
- Internal operations docs.
- Department-specific docs.
- Customer records with strict ACL.
- Restricted corpora only after explicit security/legal approval.
At each stage, measure:
- Answer helpfulness.
- Citation quality.
- Refusal correctness.
- Access-denied retrieval rate.
- Stale-source rate.
- User reports of missing or wrong sources.
Do not do this yet
Do not index “all company docs” into one assistant.
Do not rely on prompt instructions to enforce permissions.
Do not log full retrieved chunks for sensitive corpora without a clear retention and access policy.
Do not mix HR, legal, customer, and public docs in the same corpus.
Do not let the RAG answer outside its allowed sources just to be helpful.
Permission boundaries come first
Company knowledge RAG is valuable because it brings source-grounded answers into daily work. It is risky because source-grounded answers can still leak information.
Design permission boundaries first. Filter before retrieval. Separate corpora by audience. Preserve source metadata. Refuse safely. Log carefully. Test with real permission profiles. If a user cannot access the source directly, the RAG should not use that source to answer them.



