Skip to content
GuideAI Security
Xither Staff9 min read

RAG & Retrieval · Security guide

Securing Enterprise RAG: Access Control, Multi-Tenancy, and Vector Store Security

A RAG pipeline copies permissioned documents into a vector index that will answer whoever asks. Securing it means three decisions: enforce document-level ACLs at query time (not in the prompt), pick a tenant-isolation model whose blast radius you can live with, and treat the vector store — embeddings included — as sensitive data with encryption, private networking, and audit logging.

In this guide · 8 steps
  1. 01By the numbers
  2. 02Why RAG breaks your existing access model
  3. 03Document-level access control: three patterns, one sharp edge
  4. 04Multi-tenant isolation: pick your blast radius
  5. 05The vector store is a database — secure it like one
  6. 06Embeddings leak: the inversion problem
  7. 07Honest objections
  8. 08The read

Every enterprise RAG deployment quietly performs the same risky move: it copies documents out of systems that enforce permissions — SharePoint, Confluence, Google Drive, data lakes — into a vector index that, by default, enforces none. The retriever will hand any indexed chunk to any caller. Securing RAG means putting authorization back at the only place it can hold: retrieval time.

This guide covers the three layers that decision, taken together, actually requires: document-level access control enforced at query time, tenant isolation for multi-tenant B2B products, and the security posture of the vector store itself — including the least intuitive part, that the embeddings are themselves recoverable, sensitive data.

1. By the numbers

92%

of 32-token text inputs were recovered exactly, word for word, from their embeddings by an iterative inversion method — embeddings are not anonymized data.[^arxiv-2310-06816]

arXiv: Text Embeddings Reveal (Almost) As Much As Text

4

distinct document-level access-control approaches now offered by Azure AI Search alone: string security filters, POSIX-like ACL/RBAC scopes, Purview sensitivity labels, and SharePoint ACL ingestion — three of the four still in preview.[^msft-search-doclevel-2026]

Microsoft Learn, Azure AI Search

3

security layers stand between a request and your data in Amazon OpenSearch Service — network (VPC), the domain access policy, and fine-grained access control down to the document and field level. RAG teams routinely configure only the first.[^aws-opensearch-fgac-2026]

AWS OpenSearch Service documentation

2. Why RAG breaks your existing access model

Source systems enforce permissions at read time: when a user opens a file, the system checks their identity against an ACL. A RAG pipeline reads those files once, with a privileged service account, then serves their contents forever through a different door. The original ACL check never fires again. Unless permissions travel with the content and get re-evaluated on every query, your RAG system is a permission-laundering machine: it takes documents readable by few and makes their contents retrievable by many.

The failure is worse than classic over-broad search, because the LLM synthesizes. A user who could never open the compensation file can still ask "what's the salary band for L7 engineers?" and get a fluent answer grounded in a chunk they were never entitled to see. Post-hoc output filtering cannot reliably catch this — the leaked fact arrives paraphrased. The only robust control point is before the model sees the chunk: filter the retrieval, not the response.

Platform vendors have converged on exactly this design. Amazon Bedrock's managed Knowledge Bases ship connectors for enterprise repositories "along with document-level permission filtering using Access Control Lists (except for Web Crawler) at retrieval time"[4] — and AWS notes that document-level permissions are a managed-offering capability, not something you get for free when you roll your own pipeline on a raw vector store.[4] Azure AI Search enforces the same idea through query-time checks: attach the caller's Microsoft Entra token to the query via the x-ms-query-source-authorization header, and the service compares the token's user, group, and scope claims against permission metadata stored alongside each indexed document, returning only documents the caller is authorized to read.[2]

3. Document-level access control: three patterns, one sharp edge

PatternHow it worksWhat to watch
Post-retrieval filtering in app codeRetrieve broadly, then drop unauthorized chunks before promptingSlowest and most fragile: every new code path is a new bypass; Microsoft explicitly positions in-pipeline filtering as faster than loading larger result sets and trimming in the application[^msft-search-doclevel-2026]
Metadata security filters at query timeStore principal IDs on each document; the query carries a filter matching the caller's groups[^msft-search-trimming-2026]The principal "is just a string" — Microsoft's docs are explicit that this pattern simulates document-level authorization with no actual authentication of the principal[^msft-search-trimming-2026]; the filter's correctness is your app's job
Native token-based enforcementThe search service validates the caller's identity token and trims results against synchronized ACL metadata (Azure AI Search preview; Bedrock managed KBs)[^msft-search-doclevel-2026][^aws-bedrock-kb-2026]Enforcement is only as fresh as the last ACL sync; several implementations are still preview APIs
Where document-level enforcement can live in a RAG pipeline, from weakest to strongest.

The metadata-filter pattern deserves respect and suspicion in equal measure. Done well — Azure's documented approach uses a filterable, non-retrievable field of group identifiers and a search.in filter function that keeps response times subsecond even with long group lists[5] — it is fast, platform-agnostic, and generally available. But Microsoft's own description is candid: "There's no authentication or authorization through the security principal. The principal is just a string, used in a filter expression."[5] If your application forgets the filter on one query path, nothing downstream notices. Token-based enforcement moves that failure mode from your code into the platform, which is why it's worth adopting as it matures.

The sharp edge nobody budgets for is ACL synchronization. Query-time enforcement evaluates the caller against permission metadata already stored in the index — so a permission revoked in SharePoint or your IdP is still honored in RAG results until the next sync writes the change through. Azure's docs state this plainly: permission changes in the source system "are only reflected in search results after that metadata is synchronized to the index," via an indexer run, push-API update, or policy refresh.[2] That lag is a standing access-revocation gap. Treat ACL freshness as an SLA with a number attached, and design your connector layer to honor it — the connector-side mechanics are covered in depth in /guides/enterprise-rag-connectors.

Chunking silently drops permissions

ACLs attach to documents; retrieval serves chunks. If your pipeline splits documents after permissions are extracted, the permission metadata must be explicitly projected onto every chunk row — Azure's documentation warns that when a skillset chunks documents, ACL fields move from field mappings to index projections, and "without this projection, chunk-level references aren't filtered."[2] Audit this specific seam in any pipeline you build or buy. How metadata should ride through ingestion and chunking is the subject of /guides/rag-ingestion-and-chunking.

4. Multi-tenant isolation: pick your blast radius

For B2B SaaS teams putting RAG into their product, the access-control question compounds: it's no longer which employee sees which document, but which *customer's* corpus a query can touch at all. A cross-tenant leak is not an incident, it's a churn event and probably a breach notification. The architecture decision is which isolation boundary you buy: a shared index with tenant filters, an index per tenant, or a dedicated deployment per tenant.

ModelIsolation boundaryTradeoff
Shared index + tenant filterA metadata predicate on every queryCheapest and most elastic; the blast radius of a single missing or malformed filter is every tenant in the index
Index per tenantA logical index inside a shared serviceQuery scoping is structural, not conditional; capacity can be oversubscribed across tenants, but platform ceilings apply — an Azure AI Search S3 service is designed for a maximum of 200 indexes[^msft-search-multitenant-2026]
Service/deployment per tenantA dedicated service instanceMicrosoft describes this as the maximum level of isolation, with dedicated storage, throughput, and per-tenant API keys[^msft-search-multitenant-2026]; costs scale linearly with tenant count and tier upgrades may require manual data migration[^msft-search-multitenant-2026]
The three tenancy models Microsoft documents for Azure AI Search generalize to most vector stores.[^msft-search-multitenant-2026]

The honest way to choose is by blast radius, not by cost sheet. A shared index with tenant tagging fails open: one bug in filter construction — a null tenant ID, an OR where an AND belonged, a new query path that skips the middleware — and tenant A retrieves tenant B's contracts. An index or namespace per tenant fails closed: a routing bug sends a query to the wrong index and returns wrong-but-isolated results, or nothing. Microsoft's guidance also documents a hybrid: dedicated services for the largest or most regulated tenants, index-per-tenant for the long tail.[6] That maps cleanly to how most B2B contracts actually tier.

5. The vector store is a database — secure it like one

Vector stores tend to enter organizations through ML teams, not database teams, and they often skip the hardening checklist every relational store gets by default. The baseline is well documented by the platform vendors. Azure AI Search encrypts all data at rest with 256-bit AES using FIPS 140-2 compliant, service-managed encryption, enforces TLS 1.2 or 1.3 on every connection, and supports customer-managed keys as a second encryption layer plus Private Link endpoints for network isolation.[7] Amazon OpenSearch Service goes further and makes hygiene a precondition: enabling fine-grained access control *requires* HTTPS for all traffic, encryption of data at rest, and node-to-node encryption — and once enabled, it cannot be disabled.[3] On Google Cloud, Vertex AI's generative-AI security controls include customer-managed encryption keys, Access Transparency, and Data Access audit logs.[8]

Fine-grained access control in OpenSearch is also a working model of what "least privilege inside the index" looks like for RAG: roles can combine cluster, index, document-level, and field-level permissions, where document-level security restricts which documents a role can see via a query, and field-level security or field masking hides or anonymizes specific fields in results.[3] That is the same enforcement primitive as RAG permission filtering, applied one layer down — and it composes with it.

Audit logging is where assumptions go to die. Compliance teams routinely assume the search layer can answer "who retrieved this document?" — and it often can't. Azure AI Search, for instance, logs create, read, update, and delete operations and query text, but "doesn't log user identities, so you can't refer to logs for information about a specific user."[7] If per-user retrieval attribution matters for your audit posture — and for HR, legal, or clinical corpora it will — you must log it yourself at the application or gateway tier, where the caller's identity is known. Verify this capability during vendor selection, not during your first incident.

6. Embeddings leak: the inversion problem

The most common security shortcut in RAG architectures is treating vectors as safely abstract — "we only replicate the embeddings, not the text." The research says otherwise. Morris et al. framed embedding inversion as a controlled generation problem and found that "a multi-step method that iteratively corrects and re-embeds text is able to recover 92% of 32-token text inputs exactly," and demonstrated recovery of full names from a dataset of clinical notes.[1]

Text embeddings reveal (almost) as much as text.
Morris, Kuleshov, Shmatikov, and Rush — title of arXiv:2310.06816

The architectural consequence is simple: every control you apply to source documents applies to their embeddings. Vector stores inherit the data classification of the most sensitive document they index. Embeddings cross the same residency boundaries as text for sovereignty purposes. And an attacker with read access to the raw vectors — a leaked API key, an over-permissive analytics replica, a decommissioned index that never got deleted — should be modeled as having read access to the corpus.

7. Honest objections

"Metadata filtering is just a WHERE clause — one bug and it all leaks, so it's disqualified." Partly right, and the blast-radius framing above takes it seriously. But the steelman cuts the other way too: filter-based trimming is the pattern the platform vendors themselves document and ship,[5] and per-tenant physical isolation has its own failure modes — tenant-routing bugs, index-count ceilings,[6] and an operational surface that grows with every customer. The defensible position is not "filters are unsafe" but "filters assembled ad hoc in application code are unsafe." Centralize filter construction in one enforced middleware path, prefer platform-enforced token checks where available, and test the negative case in CI.

"The model is the real leak, not retrieval." Also partly right. Retrieval-time access control is necessary, not sufficient: a RAG-backed agent with tool access can still be steered into exfiltrating whatever it can legitimately retrieve, which is a governance problem — identity for agents, egress controls, human checkpoints — covered in /guides/agent-governance-guide. But the dependency runs one way. If retrieval is unfiltered, no amount of model-side guardrailing saves you; if retrieval is correctly scoped, model-side failures are bounded by what the caller was allowed to see anyway. Fix retrieval first.

"Inversion is a lab attack; nobody is reconstructing our corpus from vectors." Fair as a likelihood estimate, weak as an architecture principle. The inversion result matters less as an active threat than as a classification ruling: it removes the argument that a vector store is out of scope for data-protection controls because it holds "derived" data.[1] The cost of accepting that ruling is low — encrypt, isolate, delete on offboarding — and the cost of arguing it in front of a regulator after a vector-store exposure is not.

8. The read

Securing enterprise RAG is three decisions, made explicitly rather than inherited from defaults. First, enforcement point: document-level permissions are enforced at query time, in the retrieval platform where possible, in one centralized middleware where not — never post-hoc on model output. Second, tenancy: choose isolation by blast radius and contract tier — shared-index filtering for the cost-sensitive long tail, index- or service-per-tenant where a filter bug would be unsurvivable. Third, classification: the vector store carries the same sensitivity, residency, and audit obligations as the documents it indexes, because its contents are recoverable. Teams that write these three decisions down before the pilot ships spend their security review defending choices; teams that don't spend it re-architecting.

How to apply this

  • Inventory every corpus feeding retrieval and record its most sensitive document class — that class is now the vector store's classification.
  • Enforce document ACLs at query time: prefer platform-native token-based enforcement (Bedrock managed KBs, Azure AI Search query-time checks) over string filters, and string filters over app-side trimming.
  • Centralize filter construction in a single retrieval gateway; add CI tests that assert an unauthorized principal retrieves zero chunks from a seeded secret document.
  • Verify permission metadata survives chunking — confirm ACL fields are projected onto every chunk, not just parent documents.
  • Set an ACL-freshness SLA and measure it: time from revocation in the source system to enforcement in retrieval results.
  • Choose the tenant-isolation model per contract tier; document the blast radius of each and get it signed off by whoever owns customer trust.
  • Turn on the vendor baseline everywhere: encryption at rest, TLS-only, private networking, customer-managed keys where policy requires them.
  • Close the audit gap: log caller identity, query, and retrieved chunk IDs at the gateway, because the search layer may not attribute retrievals to users.
  • Treat embeddings as sensitive data in every DPIA, residency map, and offboarding runbook — deletion of a tenant means deletion of their vectors.
  • Re-review quarterly: several document-level enforcement features are preview APIs and their guarantees and limits are still moving.

Sources

Every quantitative or attributed claim above is linked to a primary source. Last verified at publication.

  1. [1]
    Text Embeddings Reveal (Almost) As Much As Text
    arXiv (Morris, Kuleshov, Shmatikov, Rush) · · accessed
  2. [2]
    Document-Level Access Control - Azure AI Search
    Microsoft Learn · · accessed
  3. [3]
    Fine-grained access control in Amazon OpenSearch Service
    Amazon Web Services · accessed
  4. [4]
  5. [5]
    Security Filter Pattern - Azure AI Search
    Microsoft Learn · · accessed
  6. [6]
    Multitenancy and Content Isolation - Azure AI Search
    Microsoft Learn · · accessed
  7. [7]
    Data, Privacy, and Built-in Protections - Azure AI Search
    Microsoft Learn · · accessed
  8. [8]
    Security controls for Generative AI on Vertex AI
    Google Cloud · accessed
Steps8