Skip to main content
NELLA Labs

Applied AI

Your RAG system is a data leak waiting to happen

Most retrieval-augmented generation systems enforce permissions at indexing time, or not at all. Both are wrong, and the failure is invisible until it is severe.

NELLA Labs Engineering · Platform and product engineering8 min read

The standard enterprise search demonstration goes like this: point an ingestion pipeline at a document store, embed everything, and let a model answer questions with citations. It works immediately, which is exactly the problem — because the version that works immediately has no concept of who is asking.

Three ways teams get this wrong

  1. No permission model at all. Everything is indexed, everyone can retrieve everything. This is usually described as "we will add permissions later", and later is usually after someone asks the assistant what the redundancy plan is and gets an answer.
  2. Permissions applied at indexing time. The index is filtered per user or per group at build time. This appears rigorous, but permissions change and indexes lag. A person who left the finance team last week can still retrieve last quarter's figures until the next full reindex.
  3. Permissions applied to the final answer. Retrieval is unrestricted, and a filter attempts to redact the response. The model has already read the content, and the leak now happens through summarisation, inference and follow-up questions rather than through direct quotation.

The correct boundary is query time, against the source system

Retrieval must be filtered at query time using the requesting user's current entitlements, resolved from the system that owns the document — not from a copy of its permissions taken at ingest. That means the index stores a stable reference to the source object's access-control identity, and the retrieval query joins against the caller's effective entitlements before any candidate is scored.

Concretely, in Postgres with pgvector, this means the similarity search is not a standalone vector query. It is a vector query constrained by a permission predicate that row-level security enforces regardless of what the application code asks for.

-- The RLS policy is the boundary, not the WHERE clause the app remembered to add.
create policy chunk_read on document_chunks
for select using (
  exists (
    select 1
    from document_grants g
    where g.document_id = document_chunks.document_id
      and g.principal_id = any (current_effective_principals())
      and g.revoked_at is null
  )
);

-- The application query cannot widen this, only narrow it.
select chunk_id, content, 1 - (embedding <=> $1) as score
from document_chunks
order by embedding <=> $1
limit 40;

Two consequences worth planning for

First, retrieval quality drops when the permission filter is restrictive, because the candidate pool shrinks. Retrieve a larger candidate set before reranking to compensate, and measure quality per permission profile rather than as a single aggregate number — an assistant that works brilliantly for administrators and poorly for everyone else will read as broken to most of its users.

Second, "I cannot find anything about that" and "you are not permitted to see anything about that" are different answers, and the difference itself can leak information. In most enterprise contexts the honest response is the safer one: tell the user that relevant material exists but is not available to them, and give them a route to request access. Silent absence teaches people the assistant is unreliable, which costs you the adoption you built it for.

RAGsecurityretrievalpermissions

Related

Identity and Trust

Identity verification is an orchestration problem, not an integration problem

Teams integrate a verification vendor per country and end up with several incompatible processes and no single audit trail. The fix is to make the sequence itself the thing you build.

7 min read

Technology in Africa

Designing for the connection your users actually have

Building for Ghana and Nigeria changes architecture decisions that a London-only product never has to make. Most of them are about payload size and failure behaviour, not device capability.

6 min read

Responsible AI

Screen for high-risk processing during discovery, not before launch

A data protection impact assessment discovered two weeks before go-live is a schedule problem. Discovered during discovery, it is a design input.

6 min read

Service

Automate

Apply AI and automation where they measurably pay for themselves.

Next step

Dealing with this yourself?

Tell us what you are building. The Project Architect turns a rough description into a structured brief with an architecture direction.