# LiteLLM semantic cache tenant isolation bypass (CVE-2026-89032)

> CVE-2026-89032 is a tenant isolation bypass in the LiteLLM proxy semantic cache. Users with different virtual API keys can share a cache bucket, so they can read other tenants' cached responses and receive cached tool calls. NVISO demonstrated PII leakage, hallucination poisoning and tool-call poisoning in lab PoCs; the fix shipped in v1.101.0-rc.1.

- **Published:** 2026-11-14T12:14:57Z
- **Last reviewed:** 2026-11-14T12:14:57Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-6074
- **Card image:** https://intel.threadlinqs.com/og/threat/TL-2026-6074.png
- **ID:** TL-2026-6074
- **Severity:** HIGH (CVSS 8.7)
- **Category:** VULNERABILITY
- **Status:** PATCHED
- **Detections:** 9 (1 shown free below) · **IOCs:** 5 (1 shown free below)
- **CVEs:** CVE-2026-89032

## Description

CVE-2026-89032 affects BerriAI LiteLLM before 1.101.0-rc.1. Per the VulnCheck CNA record, the root cause is a metadata key mismatch between _get_semantic_cache_tenant_scope() and _get_metadata_variable_name(). Because of it, the tenant scope key used by the semantic cache does not include the end-user identity by default. An authenticated user holding a valid virtual key can submit semantically similar prompts to affected routes (/v1/responses and /bedrock/*) and receive responses cached for other tenants. These can contain PII, financial data or source code.

NVISO found the flaw during an independent code review and published a write-up on 2026-11-12. The lab setup used LiteLLM v1.99.0 with cache type redis-semantic (Redis backend, PostgreSQL for the LiteLLM database), an Azure text-embedding-3-large embedding model, and a deliberately low similarity_threshold of 0.2. NVISO notes that production thresholds of 0.85-0.95 make exploitation harder, although the isolation failure itself remains.

NVISO demonstrated three impacts. (1) PII leakage: a victim's support-ticket prompt containing name, email, phone, date of birth, partial SSN, account number and address was cached. A second key's vaguely similar prompt about a missing paycheck returned the victim's data. (2) Hallucination poisoning: an attacker with a system prompt discouraging 'I do not know' answers asked about a non-existent PS5 Pro flash sale. The model invented a price and promo code, and a later user asking a similar question received the cached fabricated answer. (3) Tool-call poisoning: using a mock bank MCP server exposing send_transaction, an attacker-cached tool call (a transfer to an attacker account) was served to a victim whose request was semantically similar, and it executed. NVISO also describes how a cached bash tool call served to a coding agent could lead to arbitrary command execution, but does not show a full PoC for it.

The vendor fix adds an opt-in cache_params.semantic_cache_scope: end_user setting (PR 39590, commit 16db51e2). Disclosure timeline per NVISO: reported via GitHub security advisory on 2026-06-28, report closed 2026-08-04, handed to VulnCheck 2026-08-28, patch released 2026-09-04, CVE assigned 2026-09-25. No in-the-wild exploitation is reported, the CVE is not in CISA KEV, and the CISA ADP SSVC entry lists Exploitation: none. No threat actor is attributed.

## MITRE ATT&CK

- T1190 Exploit Public-Facing Application
- T1078 Valid Accounts
- T1213 Data from Information Repositories
- T1565.001 Stored Data Manipulation
- T1657 Financial Theft
- T1059 Command and Scripting Interpreter
- AML.T0053 AI Agent Tool Invocation
- AML.T0057 LLM Data Leakage

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**LiteLLM Semantic Cache Entry Served Across Multiple Virtual Keys (CVE-2026-89032)** (`TL-2026-6074-SPL-001`)

Detects the CVE-2026-89032 tenant isolation failure in the LiteLLM proxy semantic cache: a single cache entry on the affected /v1/responses and /bedrock/* routes being hit by more than one virtual API key. Because the tenant scope omits end-user identity, a second key with a semantically similar prompt receives another tenant's cached response (PII, financial data, poisoned answers).

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1190, T1078, T1213
- **Data sources:** litellm_spend_logs, litellm_proxy_logs
- **Severity:** high
- **Confidence:** high

### Splunk SPL

````spl
index=litellm sourcetype="litellm:spendlogs" earliest=-24h (request_path="/v1/responses" OR request_path="/bedrock/*")
| eval cache_hit_flag=if(lower(tostring(cache_hit))="true",1,0)
```CVE-2026-89032: one cache entry reached by more than one virtual key means the tenant scope failed```
| stats count AS requests sum(cache_hit_flag) AS cache_hits dc(api_key) AS distinct_virtual_keys values(api_key) AS virtual_keys values(end_user) AS end_users values(model) AS models min(_time) AS first_seen max(_time) AS last_seen BY cache_key
| where cache_hits>0 AND distinct_virtual_keys>1
| eval first_seen=strftime(first_seen,"%F %T"), last_seen=strftime(last_seen,"%F %T")
| table cache_key distinct_virtual_keys virtual_keys end_users models requests cache_hits first_seen last_seen
````

### Microsoft KQL

```kql
LiteLLM_SpendLogs_CL
| where TimeGenerated > ago(24h)
| where request_path_s startswith "/v1/responses" or request_path_s startswith "/bedrock/"
// CVE-2026-89032: one cache entry reached by more than one virtual key means the tenant scope failed
| summarize requests = count(), cache_hits = countif(cache_hit_b == true), distinct_virtual_keys = dcount(api_key_s), virtual_keys = make_set(api_key_s, 20), end_users = make_set(end_user_s, 20), models = make_set(model_s, 10), first_seen = min(TimeGenerated), last_seen = max(TimeGenerated) by cache_key_s
| where cache_hits > 0 and distinct_virtual_keys > 1
| project cache_key_s, distinct_virtual_keys, virtual_keys, end_users, models, requests, cache_hits, first_seen, last_seen
| order by distinct_virtual_keys desc
```

### Sigma

```yaml
title: LiteLLM Semantic Cache Hit On CVE-2026-89032 Affected Route
name: litellm_semantic_cache_hit_affected_route
id: 3b1f6c1e-8a42-4d6a-9c11-6074a0000001
status: experimental
description: Detects a LiteLLM semantic cache hit on the /v1/responses or /bedrock/* routes affected by CVE-2026-89032. Pair with the included correlation rule to flag a single cache entry served to two or more virtual keys.
references:
    - https://blog.nviso.eu/2026/11/12/breaking-the-semantic-cache-a-litellm-case-study-cve-2026-89032/
    - https://nvd.nist.gov/vuln/detail/CVE-2026-89032
    - https://www.vulncheck.com/advisories/berriai-litellm-rc-1-tenant-isolation-bypass-via-semantic-cache-layer
author: Threadlinqs Team
date: 2026-11-14
tags:
    - attack.initial-access
    - attack.t1190
    - attack.t1078
    - attack.collection
    - attack.t1213
    - cve.2026.89032
logsource:
    product: litellm
    service: spend_logs
detection:
    selection_route:
        request_path|startswith:
            - '/v1/responses'
            - '/bedrock/'
    selection_hit:
        cache_hit: true
    condition: selection_route and selection_hit
falsepositives:
    - Same virtual key retrying an identical prompt (single-key cache reuse)
    - Shared service key intentionally used by one team
level: medium
---
title: LiteLLM Shared Semantic Cache Entry Served To Multiple Virtual Keys
id: 3b1f6c1e-8a42-4d6a-9c11-6074a0000011
status: experimental
description: Correlates cache hits on CVE-2026-89032 affected routes where one cache entry is served to two or more distinct virtual API keys within 24 hours.
author: Threadlinqs Team
date: 2026-11-14
tags:
    - attack.initial-access
    - attack.t1190
    - attack.collection
    - attack.t1213
    - cve.2026.89032
correlation:
    type: value_count
    rules:
        - litellm_semantic_cache_hit_affected_route
    group-by:
        - cache_key
    timespan: 24h
    condition:
        gte: 2
        field: api_key
level: high
```

**Known false positives:**

- Several engineers sharing one service virtual key that is intentionally scoped to a single team
- Load-balanced health-check or synthetic monitoring prompts issued with different keys against the same cache entry

**Tuning notes:** Field names (request_path, cache_key, api_key, end_user, cache_hit) follow the LiteLLM_SpendLogs schema; remap to your ingestion. Allow-list known shared service keys. Hits only appear when similarity_threshold is permissive, so raise severity when cache_params.similarity_threshold is below 0.5. After upgrading to v1.101.0-rc.1 and enabling cache_params.semantic_cache_scope: end_user, this should return zero rows.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- [indicator] Virtual Key Probing Semantic Cache For Other Tenants' Responses (locked: unlock with TL Creds)
- [indicator] Cache-Hit Response Containing PII Served On Affected Routes (locked: unlock with TL Creds)
- Direct Redis Semantic Cache Access or Tampering Outside the [indicator] Proxy (locked: unlock with TL Creds)
- [indicator] Poisoning PoC Artifacts: Attacker Account, Fabricated Promo Code, Mock Bank Tool (locked: unlock with TL Creds)
- Vulnerable [indicator] Semantic Cache Configuration (redis-semantic Without end_user Scope) (locked: unlock with TL Creds)
- [indicator] Request With MCP Tool require_approval never on Affected Route (locked: unlock with TL Creds)
- [indicator] Cached Tool Call Served From Semantic Cache (Tool-Call Poisoning) (locked: unlock with TL Creds)
- Coding Agent Spawning Shell With Download or Reverse-Shell Command (Cached Bash Tool-Call Poisoning) (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (1 of 5)

Defanged, TLP:CLEAR.

- File hash: `16db51e2cfc28e02bd460481e634a8403ea9265e`

Full set of 5 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [Breaking the Semantic Cache: A LiteLLM Case Study (CVE-2026-89032)](https://blog.nviso.eu/2026/11/12/breaking-the-semantic-cache-a-litellm-case-study-cve-2026-89032/)
- [VulnCheck Advisory: BerriAI LiteLLM Tenant Isolation Bypass via Semantic Cache Layer](https://www.vulncheck.com/advisories/berriai-litellm-rc-1-tenant-isolation-bypass-via-semantic-cache-layer)
- [NVD: CVE-2026-89032](https://nvd.nist.gov/vuln/detail/CVE-2026-89032)
- [OpenCVE: CVE-2026-89032](https://app.opencve.io/cve/CVE-2026-89032)
- [LiteLLM release v1.101.0-rc.1](https://github.com/BerriAI/litellm/releases/tag/v1.101.0-rc.1)
- [LiteLLM pull request 39590 (fix)](https://github.com/BerriAI/litellm/pull/39590)
- [LiteLLM patch commit 16db51e2](https://github.com/BerriAI/litellm/commit/16db51e2cfc28e02bd460481e634a8403ea9265e)
- [Red Hat Bugzilla 2541509](https://bugzilla.redhat.com/show_bug.cgi?id=2541509)
- [CVE Record CVE-2026-89032](https://www.cve.org/CVERecord?id=CVE-2026-89032)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-6074
