Dev.to Security 🔐 Cybersecurity 👁 0 📖 4 min read

CVE-2026-114612: CVE-2026-114612: Privilege Escalation to Proxy Admin via Cryptographic Context Reuse in LiteLLM

CVE-2026-114612: Privilege Escalation to Proxy Admin via Cryptographic Context Reuse in LiteLLM Vulnerability ID: CVE-2026-114612 CVSS Score: 9.9 Published: 2026-10-22 LiteLLM versions 1.87.0 through 1.104.0-rc.1 co

CVE-2026-114612: Privilege Escalation to Proxy Admin via Cryptographic Context Reuse in LiteLLM

Vulnerability ID: CVE-2026-114612
CVSS Score: 9.9
Published: 2026-10-22

LiteLLM versions 1.87.0 through 1.104.0-rc.1 contain a cryptographic domain separation vulnerability (CWE-269, CWE-345, CWE-441) that allows an authenticated low-privilege user to escalate privileges to full proxy administrator. The application reuses a single symmetric cryptographic context and key derivation path for both at-rest secret encryption and ephemeral UI/CLI session authentication tokens without providing Associated Authenticated Data (AAD). By submitting crafted JSON session claims into user-accessible encrypted metadata fields, an attacker can use the API-key generation flow as an encryption oracle, extract the resulting ciphertext, and replay it as a bearer token to achieve administrative control and subsequent remote command execution via the Model Context Protocol (MCP) stdio interface.

TL;DR

LiteLLM reuses the same AES-256-GCM encryption context without domain separation for both stored metadata secrets and administrative session bearer tokens. Authenticated internal users can store forged administrator JSON payloads inside API key metadata, retrieve the encrypted string, and replay it as an HTTP Bearer token to gain full proxy_admin privileges and remote command execution.

⚠️ Exploit Status: POC

Technical Details

  • CWE ID: CWE-269 / CWE-345 / CWE-441
  • Attack Vector: Network (Authenticated Low-Privilege API)
  • CVSS v3.1 Score: 9.9 (Critical)
  • EPSS Score: 0.24% (13.63th Percentile)
  • Primary Impact: Privilege Escalation to proxy_admin & RCE via MCP stdio
  • Exploit Status: Proof-of-Concept (Official E2E Regression Test)
  • CISA KEV Status: Not Listed

Affected Systems

  • BerriAI LiteLLM Proxy Server
  • Chainguard LiteLLM Container Images
  • litellm: >= 1.87.0, < 1.100.4 (Fixed in: 1.100.4)
  • litellm: >= 1.101.0, < 1.101.3 (Fixed in: 1.101.3)
  • litellm: >= 1.102.0, < 1.102.2 (Fixed in: 1.102.2)
  • litellm: >= 1.103.0, < 1.103.1 (Fixed in: 1.103.1)
  • litellm: >= 1.104.0-rc.1, < 1.104.0-rc.2 (Fixed in: 1.104.0-rc.2)

Code Analysis

Commit: 1d5fdc8

Enforce cryptographic domain separation for session bearer tokens via AES-256-GCM AAD and litellm_login_ prefix

File: litellm/proxy/auth/auth_checks.py
@@ -3327,13 +3327,16 @@ async def get_org_object_by_alias(
+LITELLM_SESSION_TOKEN_PREFIX: Final = "litellm_login_"
@@ -3359,7 +3362,7 @@ def get_experimental_ui_login_jwt_auth_token(user_info: LiteLLM_UserTable) -> st
-        return encrypt_value_helper(valid_token.model_dump_json(exclude_none=True))
+        return encrypt_bearer_token(valid_token.model_dump_json(exclude_none=True), prefix=LITELLM_SESSION_TOKEN_PREFIX)
@@ -3428,7 +3431,7 @@ def get_cli_jwt_auth_token(
-        return encrypt_value_helper(valid_token.model_dump_json(exclude_none=True))
+        return encrypt_bearer_token(valid_token.model_dump_json(exclude_none=True), prefix=LITELLM_SESSION_TOKEN_PREFIX)
@@ -3438,10 +3441,10 @@ def get_key_object_from_ui_hash_key(
-        decrypted_token: Final = decrypt_value_helper(hashed_token, key="ui_hash_key", exception_type="debug")
+        decrypted_token: Final = decrypt_bearer_token(hashed_token, prefix=LITELLM_SESSION_TOKEN_PREFIX)

File: litellm/proxy/common_utils/encrypt_decrypt_utils.py
@@ -72,26 +72,55 @@ def _derive_key(signing_key: str) -> bytes:
+def _seal_aes_gcm(value: str, signing_key: str, aad: bytes | None) -> bytes:
+    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+    nonce: Final = os.urandom(12)
+    return nonce + AESGCM(_derive_key(signing_key)).encrypt(nonce, value.encode("utf-8"), aad)
+
+def _open_aes_gcm(sealed: bytes, signing_key: str, aad: bytes | None) -> str:
+    from cryptography.hazmat.primitives.ciphers.aead import AESGCM
+    return AESGCM(_derive_key(signing_key)).decrypt(sealed[:12], sealed[12:], aad).decode("utf-8")
+
+def encrypt_bearer_token(value: str, prefix: str) -> str:
+    salt_key: Final = _get_salt_key()
+    if not isinstance(salt_key, str):
+        raise ValueError("Set LITELLM_SALT_KEY or a master key to mint bearer tokens")
+    sealed: Final = _seal_aes_gcm(value=value, signing_key=salt_key, aad=prefix.encode("utf-8"))
+    return prefix + base64.urlsafe_b64encode(sealed).decode("ascii").rstrip("=")
+
+def decrypt_bearer_token(token: str, prefix: str) -> str | None:
+    salt_key: Final = _get_salt_key()
+    if not isinstance(salt_key, str) or not token.startswith(prefix):
+        return None
+    encoded: Final = token.removeprefix(prefix)
+    try:
+        sealed: Final = base64.b64decode(encoded + "=" * (-len(encoded) % 4), altchars=b"-_", validate=True)
+        return _open_aes_gcm(sealed=sealed, signing_key=salt_key, aad=prefix.encode("utf-8"))
+    except Exception:
+        return None

Commit: 9161d7f

Backport session bearer token domain separation fix to maintenance branch

Commit: 9fa1a64

Backport session bearer token domain separation fix to maintenance branch

Commit: a80eaca

Backport session bearer token domain separation fix to maintenance branch

Commit: f7cd90f

Backport session bearer token domain separation fix to maintenance branch

Exploit Details

  • GitHub (Official E2E Regression Suite): End-to-end regression test (tests/e2e/other/test_session_token_e2e.py) demonstrating the oracle encryption via /key/generate langfuse_secret_key and replay against /user/list.

Mitigation Strategies

  • Upgrade LiteLLM Proxy to the latest patched maintenance release for your deployment branch (1.100.4, 1.101.3, 1.102.2, 1.103.1, or 1.104.0-rc.2+).
  • Deploy WAF or reverse-proxy inspection rules to block HTTP Authorization headers containing 'v2:gcm:' or 'litellm_enc::' prefixes.
  • Restrict or disable Model Context Protocol (MCP) stdio transport capabilities in production environments to prevent administrative privilege escalation from translating into host command execution.
  • Disable EXPERIMENTAL_UI_LOGIN if operating legacy LiteLLM versions between 1.87.0 and 1.90.x.

Remediation Steps:

  1. Identify all deployed LiteLLM proxy instances and container images across staging and production clusters.
  2. Update the litellm Python package or container image tag to >= 1.100.4 (for 1.100.x), >= 1.101.3 (for 1.101.x), >= 1.102.2 (for 1.102.x), >= 1.103.1 (for 1.103.x), or >= 1.104.0-rc.2.
  3. Audit the LiteLLM database (specifically the LiteLLM_VerificationToken table) for API keys containing suspicious JSON strings inside metadata.logging[].callback_vars.
  4. Rotate the proxy MASTER_KEY and LITELLM_SALT_KEY if untrusted users had internal_user access while running an unpatched version.

References

Read the full report for CVE-2026-114612 on our website for more details including interactive diagrams and full exploit analysis.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.