Guide · privacy-security

How to Stop an AI Assistant Leaking Documents People Cannot Open

The index was built by a service account that could read everything, so the assistant can quote anything it crawled. Nothing errors, and the leak is found when someone reads an answer meant for others.

By stackzen-desk · Editorial reviews deskLast updated August 24, 2026

The failure that never raises an error

An internal assistant is usually built the same way: point a crawler at the wiki, the drive, the ticket system and the code host, embed everything it finds, and put a chat box in front of it. The crawler runs as a service account with broad read access, because that is the only way to reach every source without a week of permission work. That single convenience decides the security posture of the whole system.

What makes this dangerous is that it never announces itself. No request fails, no alert fires, and the assistant answers fluently and helpfully. The problem surfaces when somebody reads a response containing salary bands, an unannounced reorganisation or a legal matter they recognise as not theirs — and by then the same answer has probably been given to other people who did not mention it.

Why the index forgets who could read what

Permissions live on documents. Embeddings do not have documents; they have vectors, and a vector is a position in a space where the only surviving relationship is similarity. When content is chunked and embedded, everything the source system knew about ownership, sharing and group membership is discarded unless you deliberately carry it across.

So the retrieval step answers the question which passages are closest to this query, and closeness has no opinion about whether the person asking was ever allowed to read them. The model then does exactly what it was built to do: it writes a good answer using the material it was handed.

Carry the labels into the index

The fix begins at indexing time. Every chunk should be stored with the access metadata of the document it came from — the groups, roles, tenant identifier or document ID that governs the original — as filterable fields alongside the vector. If your vector store cannot filter on metadata efficiently, that is a reason to change the store rather than a reason to skip the control.

Attach classification too, where you have it. A tier that marks a record as restricted lets you enforce rules that are otherwise unenforceable, such as keeping the most sensitive material out of the index entirely, or allowing it to be retrieved but never sent to an external model.

Filter at query time, not after ranking

The query has to carry the identity of the person asking, and the filter has to be applied before results are ranked. Filtering afterwards is the common shortcut and it is wrong in two ways: it leaks information through result counts and timing, and it silently shrinks the result set, so a user with narrow access receives fewer and weaker passages instead of the best passages they are entitled to. That produces worse answers for exactly the people most likely to complain about them.

Keep the labels from going stale

An index is a copy, and permissions change constantly — a share revoked, a role changed, someone leaving. Re-indexing on every permission change is impractical, so most working systems re-check authorisation against the source system at answer time, but only for the handful of documents actually being used. That is affordable precisely because it is a handful, and it closes the window between a revocation and the next crawl.

Multi-tenant products need a harder line

If you are building this into a product rather than for one company, a filter mistake crosses a customer boundary instead of an internal one. Separate indexes or hard tenant partitions are worth the extra operational weight, because a single missing filter in a shared index is a cross-customer disclosure, and the query that exposes it can be completely innocent.

Test it like a permission system, not like a search engine

Build a small set of probe accounts with deliberately different access, and a fixed list of questions whose answers depend on documents only some of them can open. Run it on every change to the retrieval configuration and treat a leaked passage as a failing test rather than a quality issue.

Log the document identifiers behind every answer as well. Retrieval logs are what let you determine, after the fact, exactly who was shown what — and if you cannot reconstruct that from the logs, you cannot scope an incident, which means you have to assume the widest possible exposure.

More guides