Skip to content
Oct 04, 2025·8 min read

Separating Access Rights for an AI Assistant Without Leaks

Separating permissions for an AI assistant helps keep knowledge search separate from answer generation. We’ll cover the architecture, common mistakes, and checks before launch.

Separating Access Rights for an AI Assistant Without Leaks

Where the risk appears

The risk appears before the user even sees an answer. The AI assistant searches the knowledge base in fractions of a second and quickly pulls in relevant fragments. If the system searches the text first and checks permissions afterward, the dangerous moment has already happened.

It usually looks like this:

  • the user asks a question;
  • the search finds similar fragments;
  • the model receives them in context;
  • the application checks permissions too late.

For public instructions, this is not that serious. For contracts, HR files, ticket history, medical data, and internal policies, this order is already risky. Even if the interface later shows a denial, the model has already read something it should never have received.

Why blocking output is not enough

The model does not know which document is restricted for a specific employee. It works with the text it is given. If a closed fragment gets into the prompt, the model may quote it, paraphrase it, or surface one number, name, limit, or deadline. That is already enough for a leak.

The user may not get the whole file, but one well-aimed question like "what is the approval limit for procurement?" or "how is the penalty clause worded?" can sometimes reveal more than it should.

The problem often starts in search. A team indexes all documents at once, does not add access tags to each fragment, and then hopes the model will somehow "behave correctly." In practice, search pulls out the most similar piece of text, even if it sits in a restricted folder.

This can happen not only in large deployments. Even a careful internal chatbot can make this mistake if it searches before it checks permissions. In banking, telecom, or the public sector, the cost of such an error is higher: the leak may involve personal data, internal limits, and official rules.

Even if the team uses a single OpenAI-compatible endpoint or an LLM gateway, the problem does not disappear. Request routing and knowledge base access control are different tasks. The first sends the request to the right model. The second decides which text can be searched, read, and passed into context at all.

That is why the assistant’s permissions need to be built in before search and before generation. Otherwise, protection is reduced to hoping the model stays silent. It will not stay silent if you have already given it restricted text.

Which permissions need to be separated

The problem usually begins where access is treated as one simple switch: allowed or not allowed. For an assistant, that is not enough. You need to check not general access, but each action separately.

The first action is search. A user may have the right to find a document by name, tag, or topic, but not read its text. This is normal in large knowledge bases: an employee should understand that the relevant policy exists, who owns it, and where to request access. If the assistant immediately pulls fragments from the найденный file, search has already turned into reading.

The second action is reading the found fragment. It is better to check this separately for each piece of text returned by the search layer to the model. Permission to a folder or document type does not always mean permission to a specific attachment, appendix, or version. One PDF may contain both a public process description and a restricted appendix with pricing, personal data, or contract terms.

The third action is quoting. Even if the system is allowed to use a fragment in the answer, that does not mean it may show it verbatim. In many cases, it is safer to let the model use the text only as an internal source. Then the assistant answers by meaning, without inserting a paragraph from the document.

There is also a fourth check that is often skipped: keeping context in the session. The user’s permissions should live not only with the request but also with the conversation history. Otherwise, an employee opens the chat with procurement permissions, then switches to contractor mode, and the old session keeps mixing in fragments found earlier.

In practice, it makes sense to keep at least four separate rules:

  • whether the document can be searched in the index;
  • whether a specific fragment can be read;
  • whether it can be quoted or revealed verbatim;
  • whether this context can be stored in the current session.

Each operation gets its own check. Search has one, fragment selection has another, answer generation has a third, and session memory has a fourth. Yes, the code gets a little more complex. But then you do not have to investigate an incident where the bot "just briefly summarized" a restricted document.

How to build the check step by step

Permission checks should happen at least twice: before search and right before the answer is sent. One filter at the beginning is not enough. The assistant may honestly find the right document and then pull out a fragment that this user is no longer allowed to see.

First, the system needs to understand who actually asked the question. You need not only a user_id, but also role, department, project, entry channel, device type, and access expiration. The same request means different things for a contractor, a full-time employee, and a manager. The phrase "show me the contract terms" should not lead to the same answer for a lawyer and for an intern.

Then comes a coarse document filter. At this stage, the knowledge base should remove everything that does not fit the department, project, confidentiality tag, and access period. Time limits are often forgotten, even though they are a common source of mistakes. A person may have seen a document a month ago, but after moving to another team, that access has already expired.

After search, you cannot send the found chunks straight to the model. Each fragment needs to be checked again, separately. This is where leaks happen most often. The search index returns several similar paragraphs, and the model chooses the one that makes the most sense, even if it came from a restricted file.

A workable flow usually looks like this:

  1. Receive the request and bind it to a specific user and session.
  2. Pull current permissions from IAM, the HR system, or the internal role directory.
  3. Filter documents by access attributes before search and during search.
  4. Check each найденный fragment before passing it to the model prompt.
  5. Log what was requested, what was allowed, what was blocked, and why.

If access does not match, you need to block more than just a direct quote. The model should not be asked to "briefly summarize" or "explain in your own words" a restricted text. For the user, that is the same leak, just without quotation marks. The safe option is simple: the assistant says there is no access to this question and suggests requesting permission or contacting the document owner.

It is useful to separate two results. The first is what the model can use internally to understand the topic. The second is what it may show the user. Sometimes a document helps choose a general answer, but the text itself and the details cannot be revealed. In that case, the assistant answers at the level of a rule or process, without quotes and without paraphrasing restricted wording.

For ambiguous cases, you need an audit log. Record the user, their permissions, the list of documents found, the final set of allowed fragments, and the reason for each blocked piece. If requests to models go through an AI Router, it is convenient to keep such records near PII masking and key restrictions. But the gateway itself does not replace ACLs: access checks for the knowledge base still need to happen before the text reaches the model context.

How to keep the model from paraphrasing restricted text

The model paraphrases restricted text not because it bypassed something. Usually, the application simply gives it too much: the full document fragment, system fields, amounts, full names, lawyer comments. Then the assistant just formulates an answer based on what it saw.

The rule here is straightforward: the model should only see text the user already has the right to read. Not the whole document, not nearby paragraphs "just in case," but only the permitted portion. If access exists for a section but not for an appendix, the prompt gets the section without the appendix. If access exists for a customer record but not for passport details, those fields should not enter the context at all.

What to send to the model

Before sending anything to the model, it is worth doing a quick cleanup:

  • remove hidden fields, internal notes, amounts, account numbers, and personal data if they are not needed for the answer;
  • limit the quote size even for public documents so the assistant does not capture neighboring text;
  • send not the original document, but an already cleaned fragment with an access tag;
  • add a direct system rule forbidding quotation, paraphrase, and reconstruction of restricted parts from indirect clues.

This filter is needed even for harmless questions. A user may ask: "Why was the contract sent for approval?" If the model sees the entire document, it can easily add the deal amount, the approver’s name, and the disputed clause from the appendix. The question never asked for that, but the leak has already happened.

It also helps to limit the form of the answer. If there is no access, the assistant should not explain too much. A short refusal is safer than a long one. For example: "You do not have access to this section of the document." If it is possible to answer in general terms, let it do so without quotes and without details: "The reason is stated in the internal comment, but this fragment is not available to you."

It is also important to block attempts to paraphrase in the model’s own words. Many teams only forbid direct quotation and forget about rewriting. As a result, the model does not copy the paragraph, but retells it almost verbatim. In system rules, it is better to write it plainly: if a fragment is restricted, do not quote it, do not paraphrase it, do not summarize it, and do not draw conclusions from it.

If you have a RAG layer or a gateway like AI Router, the idea does not change. Permission checks need to happen before the text reaches the model context. Then the model simply will not have material it can accidentally reveal.

Example from a work chat

Run a pilot without rewriting
Keep your SDKs, code, and prompts as they are and quickly test the workflow.

These mistakes happen quietly in work chats. At first, everything looks fine: the assistant found the right document, understood the question, and is almost ready to answer. The problem begins the moment search knows more than it is allowed to show a specific person.

A sales manager writes: "What bonuses do support staff get this quarter?" The assistant finds an HR document with a payout table, grade conditions, and calculation examples. Search worked correctly, but the manager’s role does not grant access to that file.

If permissions are not separated, the model can easily paraphrase the restricted text in its own words. It may not insert a direct quote, but it can still reveal numbers, KPI thresholds, or wording from the document. To the user, this will look like a normal chat response.

One question, two different answers

The correct scenario looks different. The system first checks whether this employee may read the document itself, not just ask about the topic. After that check, the assistant answers the manager in general terms, without numbers and without quoting.

For example: "Bonuses for another department depend on role, grade, and goal completion. Exact amounts and conditions are available to HR and the department head." That answer is helpful, but it does not reveal restricted details.

An hour later, the same question is asked by an HR employee. They have access to the document, and the system confirms that before generating the answer. Now the assistant can refer to a specific clause and provide numbers from the table.

The answer for HR will be different: "For support specialists at the Middle level, the bonus is 15% of salary if KPI reaches 90%. Senior has a separate scale." These numbers are allowed because the right to read has already been confirmed.

That is what knowledge base access control is about. It is not the question itself that decides what can be shown, but the combination of three things: who is asking, which document was found, and whether its contents may be used in the answer.

Many teams make the same mistake in one place: they filter documents on the search screen, but they do not filter the context that goes into the model. Then the assistant does not show the file directly, but still retells its contents. In a work chat, that is an especially unpleasant leak because from the outside it looks polite and helpful.

A reliable setup is simple: first check access to the source and fragment, then generate the answer only from allowed context. If access fails, the model should rely on public rules or honestly say who to contact for exact data.

Where teams most often go wrong

One API instead of many
Connect 500+ models from 68+ providers through one compatible endpoint.

The mistake is usually not in the model. It appears earlier, when the team checks access too broadly. The user sees a folder or a project, and that seems like enough. But the assistant does not work with a folder; it works with text chunks from the index. If a paragraph from a restricted contract sits next to a public instruction, the model will not see the boundary on its own.

Because of that, the setup breaks in small details. The team checked permission for a knowledge base section, and a document inside that section inherited old settings. Then the index split the file into fragments, mixed them with other sources, and a quote went out in the answer that nobody intended to show.

The problem often starts with the index itself. Service policies, correspondence, contract templates, and public customer help are all put into one search space. That is indeed easier to start with, but later the filters become fragile. One missing attribute in metadata, and the model gets context from two worlds at once: public and internal.

Another pain point is the cache. The team once found good context for an answer, saved it for speed, and then reused the same set of fragments in another session. The user is new, the question is similar, the text is old. In the logs, everything looks fine: search barely ran, and the answer came back quickly. In reality, the assistant paraphrased data that the new user had no right to see.

Another common mistake sounds like this: "we told the model not to quote restricted documents in the system prompt." That is weak protection. The prompt only asks; the server decides. If the server has already put restricted text into the context window, the risk is still there. Even a careful model can reveal a fact, a number, a field name, a contract term, or simply paraphrase the meaning.

I would treat the prompt as an extra seatbelt, not as a lock on the door. Real checking lives on the server: before search, during fragment selection, and again before the answer. If you already have audit logs, PII masking, or a gateway like AI Router, that helps with incident analysis and keeping data organized. But by itself, it does not fix access rights.

There is also a less visible failure: teams do not record denials and borderline answers. They log successful requests, while treating all "access denied" responses as noise. Then it becomes impossible to understand why the assistant is sometimes silent and sometimes suddenly too detailed. A denial log quickly shows weak points: which source misfires most often, where the cache outlives the session, and which roles conflict with each other.

Check at least three things:

  • whether you filter access at the level of each fragment, not just the folder or collection;
  • whether the internal index is separate from the public knowledge base;
  • whether you clear the context cache when the user, role, or channel changes.

If you do not have a clear answer to even one of these questions, the leak risk is already close. Usually it comes not through a breach, but through a convenient temporary setting that was later forgotten.

Quick check before launch

Before launch, it is worth running a short but strict leak test. Many teams only look at whether the user got an answer. You need to look at something else: exactly what the system searched, what it was allowed to read, and what it later showed in the chat.

If those three steps are merged into one rule, a mistake is almost inevitable. An assistant can have different permissions for search, reading, and quoting. A user may have the right to know that a document exists on the topic, but not see the text itself. Or they may be allowed to see the contract summary, but not the client name, amount, or appendix quote.

Mini-check

Before release, five points are usually enough:

  • verify that search, reading, and quoting rules are defined separately;
  • ask the same question from different roles: employee, manager, auditor, external contractor;
  • look at the answer without access: it should not contain names, amounts, contract numbers, or even short fragments of the source text;
  • open the logs and make sure the reason is visible: access allowed, access denied, document found but reading blocked;
  • assign who changes permissions and who reviews the logs. These are not always the same person.

The same question from different roles often exposes a weak spot in five minutes. For example, a manager and an accountant ask: "What discount was approved for the client under the March contract?" The accountant may see the number and the basis. The manager without the right access should get a neutral answer like "I can’t show the contract details." If the refusal contains an amount, a surname, or a piece of wording, the check has already failed.

Logs are not there just for show. The team should be able to understand from them why the assistant answered or refused. If the log only shows the final text, incident analysis will drag on. You need at least the user role, the list of checked rules, the identifier of the found document, and the reason for blocking.

Also test paraphrasing separately. The model may not insert a direct quote, but still reveal the meaning of a restricted paragraph in its own words. So do not only test the request "show me the document". Try softer variants too: "briefly explain," "summarize the gist," "name the exceptions."

If you already have audit logs and key-level restrictions, as is common in corporate LLM gateways, this kind of test goes faster. But even good infrastructure will not save you if the team has not agreed on who grants permissions and who checks the logs afterward.

What to do next

Launch open-weight models
Try options on your own GPU infrastructure if latency and data residency matter.

If the assistant already works with internal documents, do not stretch the fix over months. Most of the risk can be reduced in one sprint if you start not with the model, but with the rules that decide whether it gets access to text at all.

First, build a role matrix on one sheet. Not with a vague phrase like "the employee sees their own stuff," but by action: who can find a document, who can read a fragment, who can get a short summary, who can see the source title, who can pass the file into the prompt. Such a table quickly shows gaps. Very often search is already open, while paraphrasing was never blocked separately.

Then take three restricted scenarios and run them manually. Simple but unpleasant cases work well: a manager asks to summarize another department’s contract, an operator asks about an internal policy without access, an employee asks to "explain in your own words" a restricted instruction. Look not only at the final answer. Check what the system found, which fragment it sent to the model, and what it recorded in the log.

After that, define red tests. They are needed to catch a leak before release. A test should fail if the assistant:

  • reveals a restricted fragment in full or in parts;
  • paraphrases the meaning of a document without read access;
  • reveals the file name, number, or author if those fields are also restricted;
  • bypasses the restriction through chat history, cache, or a repeated question phrased differently.

Next, bring protection into one place. Audit, PII masking, and request limits should work together. If they live in different services and with different teams, the gap often remains between them. When checks run in one chain, it is easier to see who requested the document, what the system hid, and where it stopped the answer.

If the team already routes LLM requests through AI Router at airouter.kz, it is convenient to keep model routing, audit logs, PII masking, and key limits there. This makes incident analysis easier and helps avoid spreading control across different parts of the stack. But the basic rule does not change: access to text is checked before the document or fragment reaches the model.

A good working criterion is simple: a user without permissions gets neither a quote, nor a paraphrase, nor even a small hint about the contents of a restricted document. If the system can hold that line in manual runs and tests, it is ready for a live chat.

Separating Access Rights for an AI Assistant Without Leaks | AI Router