This article describes a cross-tenant data-leakage vulnerability in multi-tenant RAG systems where caching mechanisms key embeddings or results by document hash alone, omitting the tenant identifier. When one tenant's confidential document is cached and another tenant's query resolves to the same cache key, the second tenant receives the first tenant's private data. The vulnerability demonstrates why isolation logic must be embedded in cache keys themselves, not just enforced at the access-control layer.
- Cache-key design flaw enables data crossingVectorBot caches embeddings using only the document hash as the key, with no tenant component. When tenant B issues a query that hashes to the same value as tenant A's confidential document, tenant B receives tenant A's cached private result, including sensitive findings. The system treats identical content hashes as identical cache entries regardless of ownership.
- Isolation checks do not protect cachesThe article emphasizes that tenant isolation enforced elsewhere in the pipeline—such as in access-control checks before cache lookup—does not protect the cache itself. Once a cache hit occurs on a key lacking tenant identity, the cached content is served to whoever triggered the matching key, bypassing any downstream validation.
- Attack requires query-to-key collisionThe attacker must craft a query that resolves to the same cache key as the victim tenant's confidential document. By confirming the key is document-hash-only and issuing a query that produces the same hash, the attacker hits the shared cache entry and retrieves the victim's private data without additional exploitation.
- Tenant identity must be in the keyThe core defense is to include tenant_id in every cache key—for example, hash(tenant_id, query/embedding). This ensures that even if two tenants query identical content, their cache entries remain separate and one tenant can never retrieve another's result, regardless of hash collisions or key matching.
- RAG pipelines are particularly vulnerableThe article identifies this as a common mistake in retrieval-augmented generation and embedding systems, where caching of embeddings and results by content alone is standard practice to save computation. The omission of tenant identifiers from these caches creates a direct channel for cross-tenant data leakage in multi-tenant SaaS deployments.
- Namespace isolation adds defense depthBeyond keying, the article recommends using separate cache namespaces or stores per tenant and enforcing tenant isolation within the vector store itself. This layered approach ensures that one tenant's data can never satisfy another's request even if keys somehow collide or access controls fail.
- Maps to OWASP LLM08 weaknessThe article categorizes this vulnerability under OWASP LLM08 Vector and Embedding Weaknesses from the OWASP Top 10 for LLM Applications (2025), positioning it as a known risk in shared vector stores and caches that leak data across tenants in LLM-based systems.
- Testing with multiple tenants is essentialThe article advises testing multi-tenant RAG systems with at least two tenants to confirm that one tenant can never retrieve the other's cached content. This validation is necessary because isolation logic that lives only in access checks, not in cache keys, is bypassed entirely by a successful cache hit.
Bottom line: Multi-tenant systems must include tenant identity in every cache key and enforce isolation in the cache structure itself—not just in access-control layers—because a cache hit with a tenant-blind key will serve private data to unauthorized tenants regardless of downstream validation. Auditing every cache and vector index for tenant components in the key is critical for RAG and embedding systems in SaaS environments.
📋 In this walkthrough
What this lab teaches
Multi-tenant systems must isolate tenants at every layer, including caches. When a RAG pipeline keys its embedding or result cache on content alone, a cache hit crosses the tenant boundary: tenant B's query reuses tenant A's cached, private result.
The lesson: a cache key that omits the tenant is a data-leak waiting to happen. Isolation has to be in the key, not just in the access check before the cache.
How VectorBot caches embeddings
VectorBot caches embeddings keyed by document hash. Tenant A uploads a confidential document and queries it, filling the cache. As the attacker tenant, a query that resolves to the same cache key returns A's cached result — including A's private finding.
The attack approach
- Confirm the cache key is the document hash only, with no tenant component.
- As the attacker tenant, issue a query that resolves to the same key A's content filled.
- Hit the shared cache entry rather than your own (empty) data.
- Surface the private string from A's document.
Full walkthrough (spoiler)
If you only get your own tenant's data, your query is not hitting A's key — open the steps.
Show the step-by-step solution
- Craft a query as the attacker tenant that maps to the cache key A's confidential document produced.
- Because the key has no tenant component, your query hits A's cached embedding result.
- The cached content — A's private audit finding — is returned to you.
- Surface that string and the lab marks you solved.
Why it works
The cache treats content as identity: same hash, same entry, served to anyone. Tenant isolation was enforced somewhere else, but not in the cache key, so the cache quietly becomes a cross-tenant channel.
Where this happens in the real world
Tenant-blind cache keys are a classic multi-tenant SaaS mistake, now common in RAG and embedding pipelines. It maps to OWASP LLM08 Vector and Embedding Weaknesses, where shared vector stores and caches leak data across tenants.
How to defend against it
- Key caches on tenant plus content — for example hash(tenant_id, query/embedding).
- Use separate cache namespaces or stores per tenant.
- Enforce tenant isolation in the vector store itself, not only in a pre-cache check.
- Test with two tenants to confirm one can never retrieve the other's cached content.
Try it, then go further
Reading about it is the easy part. Open the lab, try your own approach before peeking at the spoiler, and see how many attempts it takes.
