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:
- Identify all deployed LiteLLM proxy instances and container images across staging and production clusters.
- 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.
- Audit the LiteLLM database (specifically the LiteLLM_VerificationToken table) for API keys containing suspicious JSON strings inside metadata.logging[].callback_vars.
- Rotate the proxy MASTER_KEY and LITELLM_SALT_KEY if untrusted users had internal_user access while running an unpatched version.
References
- GitHub Security Advisory GHSA-7hp6-4w63-5g45
- NIST National Vulnerability Database (NVD) - CVE-2026-114612
- CVE.org Official Record - CVE-2026-114612
- CVE List V5 JSON Record - CVE-2026-114612
- LiteLLM Patch Commit 1d5fdc87fed66b49e1df8cf7d708ad93249eb7d0
- Wiz Vulnerability Database - CVE-2026-114612
Read the full report for CVE-2026-114612 on our website for more details including interactive diagrams and full exploit analysis.
Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.