← Blog

Vector Database Security Checklist: What to Verify Before the Index Goes to Production

Parminder Singh
Parminder Singh··5 min read
Summarize with AI

A vector index inherits the sensitivity of every document that went into it, and most access-control models were designed for rows, not for nearest-neighbour search. This checklist covers tenant isolation, permission-aware retrieval, ingestion validation, embedding inversion, deletion, and retrieval logging, mapped to OWASP LLM08:2025 and to what an auditor asks for.

Problem-Awareragvector-databaseai-securitydata-classificationowaspaccess-control
Vector Database Security Checklist: What to Verify Before the Index Goes to Production

A vector index inherits the sensitivity of every document that went into it. That is the part teams underestimate. Chunking a contract into 400 passages and embedding them does not make the contract less confidential, and the index has no column called owner to filter on, because nearest-neighbour search was never designed around row-level permissions.

OWASP tracks this as LLM08:2025 Vector and Embedding Weaknesses, and its list of mitigations is short and specific: permission-aware vector stores, validated ingestion, classified knowledge-base content, and immutable retrieval logs. The checklist below follows that shape, with the questions an auditor actually asks in each area.

TL;DR

  • A vector index is as sensitive as the most sensitive document embedded in it, so classify at ingestion, before the vectors exist.
  • Filter by the requesting user's permissions inside the search, not after it. Post-filtering still ranks documents the user cannot read.
  • Embeddings are not a form of anonymisation, because inversion research recovers meaningful source text from vectors.
  • Deleting a source document does not delete its chunks, its embeddings, or its cached retrieval results.
  • Log every retrieval: who asked, which chunks came back, and which index version answered.

1. Classify at ingestion

Decide the sensitivity class of a document before it becomes vectors, and store the class on every chunk as metadata. Retrofitting this later means re-embedding the corpus, which is the expensive version of the same job.

Keep the classes aligned with the data policy the organisation already has. A separate taxonomy invented for the AI project is one more thing to reconcile at audit time. Our guide to data classification for AI covers the taxonomy design in more detail.

Record the source system, the ingestion date, and the legal basis for holding the content. When a regulator asks why a customer record is in a model's retrieval corpus, that metadata is the answer.

2. Filter inside the search, not after it

This is the item that fails most often in review. A permission check applied to search results after ranking still lets the index rank documents the user has no right to read, and the count of returned results can leak that they exist.

Push the permission predicate into the query so the nearest-neighbour search only ever considers chunks the requesting identity can access. Most managed vector stores now support metadata filtering at query time. Confirm that the filter is applied during the search rather than as a post-processing step, because the two behave identically in a demo and differently under load when a top_k limit truncates results.

Test it with two accounts in the same tenant. Give one access to a document, deny the other, and run the same query on both. The denied account should return fewer results, not the same results with a redaction applied.

3. Prove tenant isolation

OWASP's second attack scenario is a multi-tenant vector database leaking one group's business embeddings to another group's queries. Decide whether tenants are separated by namespace, by collection, or by physical instance, then write down which one and why.

Shared-collection isolation that depends on a metadata filter is a single misconfigured query away from a cross-tenant read. That is an acceptable design for low-sensitivity content and a poor one for regulated data. My view is that if the blast radius of one forgotten filter clause is another customer's data, the isolation belongs at the collection boundary and the convenience is not worth the argument you will have later.

Run a negative test per release. One query from tenant A that should return nothing from tenant B, asserted in CI.

4. Treat ingestion as untrusted input

Anything that reaches the index can steer a later answer. OWASP's first scenario is hidden instructions inside a resume that survive into a RAG-based screening system, and the same pattern applies to any corpus that accepts outside documents.

Accept content only from sources someone has approved, and keep a record of who approved each one. Strip or neutralise instruction-shaped text during ingestion for corpora that take third-party uploads. Re-validate on re-ingestion, because a document that was clean in March can be edited in September and re-synced without review.

RAG poisoning covers the attack path in depth.

5. Stop calling embeddings anonymised

Embedding inversion recovers meaningful source content from vectors, which is why OWASP lists it as a distinct weakness. A vector store holding embeddings of personal data holds personal data, and the storage, access, retention, and transfer rules follow it there.

Encrypt the index at rest and control who can export it. A dump of raw vectors is a dump of the corpus in a form that is inconvenient to read and entirely possible to read. We wrote about the mechanics in embedding leakage.

6. Make deletion actually delete

A document deleted from the source system leaves its chunks in the index, its vectors in any replica, and its text in whatever cache sits in front of retrieval. Under GDPR Article 17, an erasure request covers the copies too.

Build the deletion path before you need it. Map each source document to its chunk IDs at ingestion, so erasure becomes a lookup instead of a scan. Then test the whole chain: source record, chunks, vectors, replicas, backups, and caches. Most teams discover the cache on the day of the first real request.

7. Log retrievals like authorization decisions

OWASP asks for immutable logs of retrieval activity, and the reason is investigative. When a model returns something it should not have, an investigator needs to know which chunks were retrieved and which identity asked. A log of prompts alone cannot answer that.

For each retrieval, keep the requesting identity, the query time, the chunk IDs returned, the filters applied, and the index version. Keep the chunk IDs rather than the chunk text where sensitivity allows, so the audit store does not become a second copy of the corpus.

DeepInspect

Most of this checklist lives inside your retrieval tier, and that sits behind the application, off the HTTP path between users and models. DeepInspect does not manage your index, enforce collection isolation, or delete your chunks.

What it governs is the step after retrieval. Once the application has assembled a prompt and is about to send it to a model, DeepInspect evaluates the identity behind that request, inspects the assembled content including the retrieved passages, enforces which model destinations are permitted, and writes a per-decision record. That covers the case where retrieval worked correctly and the resulting prompt still should not leave for a given provider.

Book a demo today.

Frequently asked questions

Does encrypting the vector database solve the access-control problem?

Encryption at rest protects the stored index from someone who takes the disk. It does nothing about a query from an authenticated user who should not see a given document, because that query is decrypted and served normally. Permission-aware retrieval is a separate control.

Is metadata filtering enough for multi-tenant isolation?

It depends on the sensitivity of the data and on how much you trust every future query path. Metadata filtering is reasonable for low-sensitivity content with a tested negative case in CI. For regulated or customer-segregated data, separate collections or instances remove the class of failure instead of testing for it.

How do we handle a document whose permissions change after ingestion?

Store the permission reference on the chunk rather than a copy of the permission itself, and resolve it at query time against the source of truth. Copying an access list into chunk metadata creates a second permission store that drifts from the first one.