LLM09: Vector and Embedding Weaknesses
RAG is where I find the most access-control bugs in AI apps, and almost none of them need a clever prompt. A vector index returns whatever is closest to the question. It has no idea who is asking, who wrote the document, or whether the document was deleted last week. We work that gap against live targets: another tenant's chunk in your answer, a net cast wider than the question, a planted document that steers the reply, a contributed page that outranks the official one, withdrawn content that keeps answering, and the second retrieval paths a filter never reached. The fix sits in the retrieval code, where the caller's identity is known. The model never sees that boundary, so it cannot hold it.
Retrieval-augmented generation works by embedding every document chunk into a vector, embedding the user's query the same way, and pulling back the chunks whose vectors sit closest. Those chunks are pasted into the model's context and the answer is generated from them. The entire security of the system rests on a question the vector index never asks: is this user allowed to see this chunk?
Closeness is usually measured as cosine similarity, a score for how nearly two vectors point in the same direction. Cosine distance is the same measure reversed, so a smaller distance means a closer match.
Nearest-neighbour search ranks by similarity, not by authorization. If a single index holds two tenants' data, or public and internal content side by side, or a document that was deleted from the UI but never purged from the store, then any query that lands semantically near a confidential chunk retrieves it. No rule was broken - the system simply let relevance stand in for permission. In this failure the confidential value is not in the system prompt. It sits inside an indexed chunk, behind a retrieval boundary that was never enforced.
The corpus is also a write surface. Wherever an untrusted party can contribute a document - a community article, an uploaded contract, a shared workspace note - they can plant a chunk that carries an embedded instruction. When an innocent question retrieves it, the assistant treats the retrieved text as guidance and obeys it. This is OWASP LLM01's indirect prompt injection delivered through the vector store, and the user who asked the question is the delivery vehicle.
Ranking compounds the problem. When a pipeline uses only the top result and ranks purely on keyword and vector similarity, an attacker who keyword-stuffs a contributed article can engineer it to outrank the authoritative source for a target query - so the answer comes entirely from the attacker's chunk. And because embeddings outlive the policies that created them, a chunk indexed when content was public stays retrievable long after the source is deleted or re-classified, unless the index is treated as a system of record with its own lifecycle.
Going deeper— Sparse vs dense retrievers under adversarial ranking
BM25 is a keyword-scoring method, and retrievers built on it are called sparse. They score on term overlap, so a document that repeats the query's exact terms scores higher. BM25 dampens this, because each extra repetition adds less and longer documents are penalized. Dense retrievers (Contriever, E5, text-embedding-ada-002) encode meaning, so repeating a term adds even less there.
Dense retrieval is still attackable, as Zhong et al. (2023) showed in "Poisoning Retrieval Corpora by Injecting Adversarial Passages". They used gradient access to a dense retriever to optimize a small set of passages toward many queries. With 50 such passages in a corpus of millions, most test queries against Contriever retrieved at least one in the top 20. Supervised retrievers were harder to fool, but up to 500 passages succeeded against every model the authors tested.
The takeaway: a dense embedder weakens the cheapest trick, raw repetition, but it does not remove the attack. Plain on-topic prose written to answer the target question still ranks near that question. The attacker needs no access to the model to write it. Trust-weighted ranking is needed with sparse and dense retrievers, and with hybrid pipelines that combine the two.
Research has shown the stored vectors are not opaque. With query access to the same embedding model, embedding-inversion attacks have recovered short passages of the original text from their vectors. A leaked or over-shared vector store is therefore not a harmless pile of numbers. The embedding is derived data that inherits the confidentiality of its source.
Going deeper— How Vec2Text reconstructs source text from embeddings
Morris et al. (2023), "Text Embeddings Reveal (Almost) As Much As Text," trained an inversion model called Vec2Text. It guesses the text, re-embeds the guess, and corrects it over up to 50 rounds, each time moving closer to the target vector. The attacker needs query access to the same embedding model. With that access, Vec2Text recovered 92% of 32-token inputs exactly for the open-source GTR-base model.
Accuracy drops for longer passages. Against OpenAI's text-embedding-ada-002 the exact-match rate was lower, and it fell sharply as inputs grew longer. The same paper recovered full names from a set of clinical notes. Earlier work by Li et al. (2023, "Sentence Embedding Leaks More Information than You Expect") had already reconstructed whole sentences from sentence embeddings.
The practical upshot: an exposed vector store is sensitive data, even without the original documents. Exposure can come from a misconfigured bucket policy, a backup leak or over-broad API credentials. Short text is the most exposed to inversion. Classify the store at the same level as its source corpus.
A vector index ranks by relevance, never by authorization, trust, or lifecycle. If your security depends on a confidential chunk simply not matching the query, you have no security. The boundary has to be enforced in the retrieval and application layer - a query-time access filter, a trust-weighted ranker, and a transactional purge - because anything reachable from the index is already disclosed.
A vector index ranks by similarity, not by authorization - relevance silently substitutes for permission unless an access filter is applied at query time, bound to the authenticated caller.
The corpus is an attacker-writable input: any contributed, uploaded, or retrieved chunk can carry an embedded instruction, so retrieved text is untrusted data, never trusted guidance.
Naive similarity ranking lets a crafted, keyword-stuffed document outrank the authoritative source - rank with provenance and trust as first-class signals, not keyword overlap alone.
Embeddings outlive their source: deletion and re-classification must be transactional with the index, because a chunk left behind keeps answering queries with secrets everyone believes are gone.
As enterprises rushed RAG into production, a recurring class of incident emerged: multi-tenant assistants built on a single shared vector index, where one customer's query could retrieve another customer's chunks because no per-request tenant filter was enforced - relevance was allowed to stand in for authorization. In parallel, academic work (notably Morris et al.'s 'Text Embeddings Reveal (Almost) As Much As Text', 2023) showed that the stored vectors are not opaque. An attacker who can query the same embedding model can reconstruct short passages of source text from their vectors. A leaked or over-shared vector store is therefore sensitive data in its own right. OWASP added Vector and Embedding Weaknesses to its Top 10 for LLM Applications in the 2025 edition, as LLM08. This path uses the 2026 numbering, where it is LLM09.
© 2026 GenAI Security Lab. All rights reserved. You may read, quote, and link to this material with attribution. Copying, republishing, redistribution, resale, or use to train models or build competing products is prohibited without prior written permission.