Home AI Solutions Ready-made Solutions Peers & Simulation RAG & Retrieval Use Cases Frameworks Blog Deutsch Contact Us
Back to the blog

The Index Knows More Than the User Is Allowed To

The assistant served three departments from one index, filtering out documents a user was not entitled to see. It worked, and a colleague demonstrated in a morning that the filtering could be inferred around.

The Design That Looked Fine

One index over all documents, and a filter applied to the candidate set so that a user only ever sees passages from documents their role permits. It is the obvious design, it is what most vector databases support directly, and it passed our own review.

A colleague spent a morning on it and produced two ways to learn about restricted content without seeing it. Neither was clever. Both are properties of the design rather than bugs in it.

Inputuntrusted Guardrailspolicies · pii Agentleast privilege ApprovalhumanActiontraced
Untrusted input arrives — treat it as data, not instructions. 1/4

What Leaks Without a Document Leaking

The first is absence. Ask a specific question about a project you should not know exists, and a system with a restricted document about it behaves differently from one with nothing: the wording of the refusal, the passages it falls back to, and the time it takes are all different.

The second is ranking. When the best matches are filtered out, what remains is the fourth, fifth and sixth best, and those are often adjacent enough to describe the shape of what was removed. Neither reveals a document. Both answer questions a user was not entitled to have answered.

The Research and What It Establishes

Tang and colleagues published work in 2026 on differentially private retrieval-augmented generation, applying formal privacy guarantees to the retrieval step rather than treating access control as a filter over results.

The framing we took is that filtering after retrieval leaves the retrieval itself observable. Formal guarantees are heavier machinery than our situation needed, and the observation that the leak is in the retrieval rather than in the output is what redirected our design.

ApproachWhat it protects
Filter results after retrievalThe document text. Not its existence
Filter candidates before rankingBetter, ranking still observable
Separate index per permission setExistence and ranking. Our choice
Formal privacy guaranteesStrongest. More than we needed

What We Changed

Separate indexes per permission set. A user's query only ever reaches an index containing documents they may see, so absence is genuinely absence and the ranking they observe is the ranking over their own corpus.

It costs more: three indexes instead of one, some documents duplicated across them, and a build process that has to know the permission model. On this corpus that was about forty percent more storage and a longer ingestion, which the customer accepted immediately once the two demonstrations had been shown.

Why Not Just One Index Per User

Because it does not scale and because permissions are not per user. There were three meaningful permission sets, not four hundred users, and building per set keeps the number of indexes proportional to the policy rather than to the headcount.

Where a permission model is genuinely per user, this approach fails and something closer to the formal work is needed. We have not built that and we would say so rather than adapt what we have to a situation it does not fit.

The Timing Detail

Even with separate indexes, a query that returns nothing is faster than one that returns something. That difference is small, we measured it, and for this deployment nobody with access to the assistant lacks access to the fact that the departments exist.

We wrote that reasoning down rather than leaving it implicit, because it is the kind of accepted risk that later looks like an oversight. The document says what we did not protect against and why the customer considered it acceptable.

How This Should Have Been Caught

By asking what an adversary learns rather than what they see. Our review had checked that documents do not cross the boundary, which they did not, and had never asked what a user could infer from the system's behaviour.

That question is now on the review checklist alongside the timing questions we added after the caching incident. Both come from the same blind spot: reviews look at payloads, and information crosses boundaries in other ways.

What We Do Not Claim

We do not claim separate indexes are sufficient. They close absence and ranking. Query patterns, cost attribution and shared model caches are other channels, and a determined internal adversary with time is not who this defends against.

We also do not claim our colleague's demonstrations were exhaustive. He found two in a morning, which is a lower bound on what exists rather than a measurement, and the honest reading of that is that we should have someone spend a morning on this more often.

Sources