Secure Prompt Routing: Stopping Cross-Tenant Data Leaks in LLMs

Posted 13 Nov by JAMIUL ISLAM — 0 Comments

Secure Prompt Routing: Stopping Cross-Tenant Data Leaks in LLMs

Imagine you build a customer support bot for two competing companies, Company A and Company B. They share your infrastructure to save costs. A user from Company A asks, "What are our Q3 sales figures?" The system retrieves the answer, but due to a subtle routing error, it accidentally pulls context from Company B’s database. The model generates a response that includes a snippet of Company B’s confidential strategy. You didn't hack the model; you just failed to lock the door on the way in.

This isn't a hypothetical nightmare. It's a common failure mode in multi-tenant Large Language Model (LLM) systems. As organizations rush to deploy Generative AI, they often treat the model as a black box, assuming that if the input is correct, the output will be secure. But in reality, the risk lies in the plumbing-the path a request takes from the user, through retrieval systems, caches, and tools, before hitting the model and coming back out. This article breaks down how to implement secure prompt routing, ensuring that Tenant A never sees Tenant B’s data, regardless of what the model "knows" or hallucinates.

The Myth of the Prompt as a Security Boundary

Many developers believe that adding a line like "You only have access to User X's data" in the system prompt is enough to enforce security. It isn't. An LLM is a probabilistic engine, not an access-control list. If sensitive data enters the context window, the model can leak it, even if instructed otherwise. More dangerously, prompt injection attacks can override these instructions entirely.

OWASP's guidance on Retrieval-Augmented Generation (RAG) security explicitly states that tenant isolation must be enforced before content reaches the model. Think of it this way: if you hand a librarian a book containing secret codes, telling them "don't tell anyone about page 42" doesn't stop them from reading it. You need to physically prevent them from opening the wrong section. In LLM systems, this means authorization decisions must happen in deterministic code-in the middleware, the vector database query, and the cache layer-not in natural language prompts.

A robust architecture treats the prompt as untrusted input. It binds every request to a verified identity and scope server-side. If the system cannot prove that the retrieved chunks belong to the authenticated tenant, it should fail closed, returning no data rather than risking exposure.

Mapping the Attack Surface: Beyond the User Input

Cross-tenant leaks don't just happen via direct user queries. The attack surface is vast and often invisible to application developers. Here are the primary vectors where data bleeds across boundaries:

  • Vector Retrieval: If your vector store uses a shared index without strict filtering, a semantic search for "revenue" might pull chunks from any tenant.
  • Response Caches: This is a silent killer. If User A asks a question and the result is cached, User B asking a similar question might get User A's answer served up, leaking context.
  • KV-Cache Sharing: Modern inference engines use Key-Value (KV) caches to speed up token generation. Research from NDSS 2025 shows that shared KV-caches in multi-tenant serving can expose prompt information through timing side-channels, even if application-level filters work perfectly.
  • Tool Execution: A model might suggest calling an API endpoint. If the tool doesn't independently verify permissions, it could fetch data the user shouldn't see.
  • Logs and Traces: Storing raw prompts and outputs in observability platforms can create a secondary database of sensitive info, accessible to admins who shouldn't necessarily see tenant-specific secrets.

You must audit every hop in the request lifecycle. Does the embedding service know which tenant sent the text? Does the cache key include the tenant ID? Is the log redacted?

Choosing Your Vector Store Isolation Strategy

When designing your RAG pipeline, you have three main patterns for handling vector storage. Each trades off operational complexity against security strength.

Comparison of Vector Store Isolation Patterns
Pattern Description Security Strength Operational Cost
Siloed Separate index/collection per tenant (e.g., Pinecone namespaces). High. Physical/logical separation prevents accidental mixing. High. Managing thousands of indices can be complex.
Pooled Single shared index with mandatory server-side metadata filters. Medium. Relies on perfect filter implementation; risky if filters bypassed. Low. Easier to manage scale and updates.
Hybrid Shared infra for low-risk data; silos for high-sensitivity tenants. Variable. Best balance for mixed-risk environments. Medium. Requires policy-aware routing logic.

For most enterprises, the Siloed approach is recommended for high-value data. OWASP suggests using namespaces supported by databases like Pinecone, Weaviate, or Qdrant. By isolating data at the storage level, you reduce the chance of a coding error in your filter logic causing a breach.

However, if you choose a Pooled design, you must enforce "pre-retrieval filtering." Never retrieve all results and then filter them in Python. That exposes similarity scores and potentially leaks metadata about restricted documents. The filter must be part of the vector query itself.

Mechanical arm filtering data particles in a digital neural network vault

Implementing Fail-Closed Routing Logic

Secure routing requires a strict sequence of operations. Trust nothing from the client. Here is the ideal flow for a single request:

  1. Authenticate & Authorize: Verify the user's session. Derive their `tenant_id` and `entitlements` from trusted server-side claims, not from a header the client can spoof.
  2. Scope Retrieval: Construct the vector query with a hard constraint: `WHERE tenant_id = current_user_tenant`. Do not rely on the model to ignore other tenants' chunks.
  3. Validate Context: Before assembling the prompt, re-check that every retrieved chunk belongs to the authorized scope. If a chunk fails validation, drop it.
  4. Assemble Prompt: Insert only validated content into the context window.
  5. Execute Tools: If the model requests a tool call, intercept it. Check if the user has permission to execute that specific action. Do not assume read-access implies write-access.
  6. Cache Safely: Generate cache keys that include the `tenant_id`, `user_role`, and a hash of the specific permissions used. If permissions change, invalidate the cache.

If any step fails-say, the authentication token expires mid-request-the system should return an empty response or a generic error, not a partial answer based on stale or unauthorized data. This "fail-closed" behavior is critical for compliance.

The Hidden Risk: Shared Inference Infrastructure

Even if your application logic is perfect, the underlying hardware might betray you. Most cloud LLM providers use multi-tenant inference clusters. To optimize GPU memory, they share the Key-Value (KV) cache between concurrent requests.

Recent academic research, including a 2025 paper from NDSS, highlights that attackers can infer information about other users' prompts by analyzing timing variations in response generation. This is known as a timing side-channel. While you can't control the provider's internal cache management, you can mitigate risks by choosing dedicated instances for highly sensitive workloads or by adding noise to your request patterns. For most SaaS applications, however, the primary defense remains rigorous application-layer isolation.

Guardian mech protecting secure server racks in a cloud infrastructure

Testing for Leaks: Adversarial Verification

How do you know your routing is secure? Unit tests aren't enough. You need adversarial integration tests that simulate real-world chaos.

Create a test suite that runs continuously in your CI/CD pipeline. Include scenarios like:

  • Cross-Tenant Query: Force a query from Tenant A that semantically matches unique data in Tenant B. Assert that zero chunks from Tenant B are returned.
  • Stale Permissions: Simulate a user losing access to a document while their session is active. Ensure subsequent queries exclude that document immediately.
  • Cache Poisoning: Prime the cache with a specific response for User A. Then, have User B ask a slightly different question that might hit the same cache entry. Verify they receive distinct, correctly scoped answers.
  • Connection Reuse: Test long-lived connections to ensure state from one tenant doesn't bleed into the next request on the same socket.

Your acceptance criterion shouldn't be "the model refused to answer." It should be "unauthorized data never entered the context window." Log the IDs of retrieved documents and verify them against the user's entitlements programmatically.

Governance and Compliance Frameworks

While technical controls are vital, governance ensures they stay in place. Align your architecture with established frameworks. The NIST AI Risk Management Framework provides a voluntary structure for documenting risks and controls. Specifically, its Generative AI Profile (NIST AI 600-1) helps map security needs to business outcomes.

Remember that data privacy laws (like GDPR or CCPA) apply to AI outputs too. If a model inadvertently reveals personal data from another tenant, it's a reportable breach. Establish clear data retention policies for logs and caches. Audit trails should record who asked what, which documents were retrieved, and which tools were executed, but avoid storing raw sensitive content in logs unless necessary and encrypted.

Key Takeaways for Implementation

Securing multi-tenant LLM systems isn't about buying a new product; it's about architectural discipline. Here is your checklist for success:

  • Identity First: Always derive tenant scope from authenticated sessions, never from client-supplied headers alone.
  • Pre-Retrieval Filtering: Enforce access controls inside the vector database query, not after retrieval.
  • Cache Scoping: Include tenant and permission levels in cache keys to prevent cross-user leakage.
  • Independent Tool Auth: Validate permissions for every tool call separately from the chat context.
  • Fail Closed: When in doubt, return no data. Partial leaks are still leaks.
  • Continuous Testing: Run adversarial cross-tenant tests in production-like environments regularly.

By treating prompt routing as a security boundary rather than a convenience feature, you protect your customers' trust and your company's reputation. The technology moves fast, but the principles of least privilege and defense-in-depth remain timeless.

Can I rely on system prompts to keep tenant data separate?

No. System prompts are natural language instructions that models may ignore or override via injection. Access control must be enforced deterministically in the application code and database queries before data enters the model's context window.

What is the biggest risk in shared vector databases?

The biggest risk is improper filtering. If you retrieve all similar chunks and filter them later, you expose metadata and similarity scores of restricted data. Always apply tenant filters within the vector search query itself.

How does caching affect multi-tenant security?

Caching can cause data leaks if keys are not scoped correctly. A response cached for one user might be served to another with different permissions. Cache keys must include tenant ID and permission hashes, and entries must be invalidated when source data changes.

Are there security risks with shared LLM inference servers?

Yes. Shared Key-Value (KV) caches in multi-tenant inference can introduce timing side-channels, where attackers infer prompt details based on response times. Dedicated instances or careful workload isolation can mitigate this.

What is the best way to test for cross-tenant leaks?

Use adversarial testing in CI/CD. Create queries from one tenant that match unique data in another. Verify that zero unauthorized chunks are retrieved and that no unauthorized data appears in logs or caches. Also test connection reuse and stale permissions.

Write a comment