Like giving every hotel guest a master keycard to the safe room because the front desk forgot to check IDs
CVE-2026-35029 is an incorrect-authorization flaw in LiteLLM's /config/update endpoint. Prior to version 1.83.0, the endpoint performs no role check — any holder of a valid API key (even the lowest-privilege internal_user role) can POST arbitrary JSON to rewrite the proxy's runtime configuration and environment variables. From there, three immediate chains open: (1) set UI_LOGO_PATH to /app/.env and call the unauthenticated /get_image endpoint to exfiltrate secrets, (2) overwrite UI_USERNAME and UI_PASSWORD to seize the admin dashboard, and (3) register a custom pass-through endpoint handler pointing to attacker-controlled Python code, achieving remote code execution running as root inside the container. Affected versions: all LiteLLM releases < 1.83.0. Fixed in v1.83.0.
The vendor's HIGH / 8.8 score is defensible but slightly generous for the *average* deployment. The CVSS vector correctly captures AV:N/AC:L/PR:L/UI:N, reflecting the low-privilege authentication requirement. However, the score assumes a uniform population. In reality, the auth barrier is porous: Wiz found ~10% of publicly exposed instances accept the default master key sk-1234 or require no authentication at all, effectively making this PR:N for a meaningful slice of the installed base. Against that slice, the real-world severity is closer to 9.8. Conversely, well-managed internal deployments behind a VPN with rotated keys face genuine friction at step one. Balancing these populations, we downgrade slightly to 8.3 — the auth prerequisite provides *some* friction, but active exploitation and default-credential prevalence prevent a larger reduction.
5 steps from start to impact.
Obtain a valid API key
internal_user. In ~10% of internet-exposed instances, the default master key sk-1234 works out of the box (Wiz, August 2026). In multi-tenant enterprise deployments, keys are distributed to developers, CI/CD pipelines, and internal tools, broadening the insider-threat surface. Alternatively, keys can be harvested from leaked .env files, git repos, or prior compromise.- Network access to the LiteLLM proxy (port 4000 by default)
- A valid API key of any privilege level
- Well-managed deployments rotate the master key and restrict key issuance to named principals
- Internal-only deployments behind a VPN reduce the unauthenticated attacker surface
litellm on port 4000 identify exposed instances.POST to /config/update — rewrite environment variables
POST /config/update with the API key in the Authorization: Bearer header. Because the endpoint lacks proxy_admin role enforcement, the request succeeds regardless of the caller's role. The attacker can set arbitrary environment variables and proxy configuration keys. This is the core authorization bypass (CWE-863).- Valid API key from Step 1
- None — the endpoint accepts any authenticated caller without further checks
POST /config/update with non-admin bearer tokens. Application logs show config mutations by non-admin users — alert on any /config/update call.Exfiltrate secrets via UI_LOGO_PATH arbitrary file read
UI_LOGO_PATH to a sensitive path like /app/.env, /etc/shadow, or cloud credential files. A subsequent unauthenticated GET /get_image request returns the file contents. This leaks all stored LLM provider API keys (OpenAI, Anthropic, Azure, AWS Bedrock), database credentials, and cloud IAM tokens. The /get_image endpoint requires no authentication, making the second half of this chain trivially accessible.- Successful config update from Step 2
- Container filesystem isolation may limit readable paths — but
/app/.envis the primary target and is always present
/get_image requests for non-image content types. File integrity monitoring on the LiteLLM config file detects UI_LOGO_PATH tampering.Admin account takeover via credential overwrite
UI_USERNAME and UI_PASSWORD environment variables via the same /config/update endpoint. This grants full administrative access to the LiteLLM dashboard, enabling the attacker to view all API keys, user configurations, spend tracking, and model routing rules. Legitimate administrators are locked out.- Successful config update from Step 2
- SSO-based admin auth (if configured) is not overridden by env vars — but most self-hosted deployments use the built-in username/password
UI_USERNAME or UI_PASSWORD in config update payloads.Remote code execution via malicious pass-through handler
exec(compile(...)) without sandboxing, running as root inside the container. This grants full container-level command execution, enabling lateral movement to cloud metadata services (169.254.169.254), persistent backdoors, and pivoting into the broader cloud environment. Wiz confirmed that IMDSv2 protections are bypassable due to header forwarding behavior.- Successful config update from Step 2
- Attacker-hosted Python payload reachable from the LiteLLM container
- Egress filtering or network policies may block the container from reaching attacker-controlled endpoints
- Container runtime security (Falco, Sysdig) may detect unusual process execution
exec() calls with external code. Network monitoring flags outbound connections from the LiteLLM container to unknown hosts.proxy_admin role enforcement on /config/update; v1.83.9 addresses additional CVEs (59821, 59822, 59823). Per the noisgate mitigation SLA for HIGH severity, deploy within 30 days. Given active exploitation, prioritize internet-facing instances within 72 hours./config/update except from known admin IPs. This is a surgical compensating control that directly breaks Step 2 of the attack chain without requiring a code upgrade. Deploy within 30 days.exec() calls and process spawning inside the LiteLLM container (Step 5 of the attack chain). Egress network policies prevent the container from reaching attacker-controlled endpoints or cloud metadata services. This limits blast radius even if the config update succeeds.- Rate limiting on the API — the exploit requires only a single POST request to
/config/update; rate limiting doesn't prevent a one-shot attack. - Read-only filesystem on the container — the vulnerability modifies in-memory configuration and environment variables, not files on disk. A read-only rootfs does not prevent exploitation.
- API key scoping / per-model permissions — LiteLLM's role-based access control is exactly what's broken here; the bug bypasses role checks entirely, so granular key scoping provides no protection on unpatched versions.
- Web Application Firewalls with generic rulesets — the payload is a legitimate-looking JSON config update; generic SQL injection or XSS rules won't flag it. You need a *specific* rule blocking the
/config/updatepath.
The supporting signals.
| In-the-wild exploitation | Active. Honeypot telemetry recorded ~3,900 requests from 73 distinct IPs targeting /config/update and admin routes post-disclosure (SecurityOnline). Automated scanning began immediately after public disclosure. |
|---|---|
| Proof-of-concept | Public. GitHub repo learner202649/CVE-2026-35029-PoC includes a Docker Compose reproduction environment. Also indexed in asvorg/CVE-2026-PoCs and SecureWithUmer/CVE-2026-PoCs. Nuclei detection template available via pentest-tools.com. |
| EPSS | 3.982% (91st percentile) — indicates notably elevated exploitation probability relative to the general CVE population. |
| CISA KEV | Not listed as of 2026-10-14. Given active exploitation evidence, KEV addition would not be surprising. |
| CVSS vector | CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H — network-accessible, low complexity, low privilege required (any API key holder), no user interaction. CVSS v4.0: 8.7. |
| Affected versions | All LiteLLM releases < 1.83.0. Downstream packages embedding litellm (e.g., prompt2model, langstream) may also be affected — check pip show litellm in all environments. |
| Fixed version | v1.83.0 (endpoint now enforces proxy_admin role). Vendor recommends v1.83.9+ for additional hardening fixes addressing CVE-2026-59822 and CVE-2026-59823. |
| Exposure data | Wiz identified 85,000+ instances in August 2026 internet scan; 3,074 confirmed reachable, of which 294 (~10%) accepted default credentials or no auth. Censys reports a 97% increase in exposed LiteLLM instances over 9 months. LiteLLM is present in ~1/3 of cloud environments (Wiz data). |
| Disclosure & credit | Disclosed 2026-04-06. Discovered by Lakera (per vendor advisory). Independent research by Mateo Rojas-Carulla (Check Point Research) and Wiz confirmed attack chains and cloud compromise scenarios. |
| Related CVEs | CVE-2026-59821 (code guardrail RCE), CVE-2026-59822 (MCP auth bypass), CVE-2026-59823 (SSRF), CVE-2026-42208 (SQL injection). LiteLLM has had 6+ CVEs in 2026 alone, indicating systemic security debt. |
Sources.
- GitHub Advisory — GHSA-53mr-6c8q-9789
- Check Point Research — LiteLLM Gateway Vulnerabilities
- Wiz — Breaking LiteLLM: From Auth Bypass to Cloud Compromise
- SecurityOnline — CVE-2026-35029 Exploited for Full Server Takeover
- LiteLLM Vendor Advisory — Security Hardening April 2026
- PoC Repository — learner202649/CVE-2026-35029-PoC
- CyberNews — Thousands of LiteLLM Instances Exposed
- Pentest-Tools — LiteLLM Arbitrary File Read Scanner
Why this verdict
- Auth barrier is real but porous: PR:L requires a valid API key, which is genuine friction in locked-down deployments. However, ~10% of internet-exposed instances accept the default
sk-1234master key (Wiz, Aug 2026), and multi-tenant deployments distribute keys broadly to developers and CI/CD. This friction reduces effective severity by ~0.3 points from the vendor baseline. - Active exploitation confirms weaponization: Honeypot data (3,900 requests, 73 IPs) and a public Docker-based PoC eliminate any theoretical-only discount. Attackers are actively probing and exploiting this chain, which prevents a larger downgrade.
- Role multiplier — credential aggregator (canonical high-value role): LiteLLM's entire purpose is aggregating API keys for LLM providers (OpenAI, Anthropic, Azure, AWS Bedrock). ≥90% of production deployments hold real API keys by definition — this is not an incidental high-value scenario, it's the product's core function. Blast radius on compromise: all stored LLM provider keys exfiltrated (tenant-scale), cloud infrastructure pivot via container metadata (cloud-account-scale), and prompt/response data exfiltration. This floors the verdict at HIGH.
- Role multiplier — cloud infrastructure pivot: Wiz confirmed that RCE on LiteLLM containers enables IAM credential theft via metadata services, even with IMDSv2, due to header forwarding. LiteLLM containers often inherit broad IAM permissions. Blast radius extends from the application tier to the cloud control plane.
- Systemic security debt increases forward risk: Six CVEs in 2026 alone (including CVSS 10.0 RCE) signal ongoing code-quality concerns. Organizations running LiteLLM should assume additional vulnerabilities will surface.
Why not higher?
CRITICAL would require either unauthenticated exploitation or a canonical infrastructure component (DC, hypervisor, network edge). LiteLLM is an application-tier component — even with its credential-aggregator role, it doesn't control identity or network infrastructure directly. The authentication requirement, while porous, is a meaningful friction point that real-world attackers must clear. CISA has not added this to KEV, and the EPSS 91st percentile is elevated but not in the top tier.
Why not lower?
The authentication barrier is significantly weakened by default credentials affecting ~10% of exposed instances and broad key distribution in enterprise multi-tenant setups. Active exploitation is confirmed — this is not a theoretical chain. The blast radius on any production LiteLLM instance is inherently high because the product *is* the API key vault. Downgrading to MEDIUM would ignore both the exploitation evidence and the canonical credential-aggregator role that floors this at HIGH.
Crowdsourced verification payload.
Run this script on any host where LiteLLM is installed (typically the container itself or the Python virtualenv hosting the proxy). Invoke with python3 check_cve_2026_35029.py. No special privileges required — it only reads package metadata via pip.
#!/usr/bin/env python3
"""CVE-2026-35029 checker — LiteLLM privilege escalation via /config/update
Outputs: VULNERABLE / PATCHED / UNKNOWN
Exit codes: 1 = VULNERABLE, 0 = PATCHED, 2 = UNKNOWN
"""
import subprocess
import sys
import re
FIXED_VERSION = (1, 83, 0)
def parse_version(v_str):
"""Parse version string to tuple of ints."""
parts = re.findall(r'\d+', v_str)
return tuple(int(p) for p in parts[:3])
def main():
try:
result = subprocess.run(
[sys.executable, '-m', 'pip', 'show', 'litellm'],
capture_output=True, text=True, timeout=30
)
except Exception as e:
print(f'UNKNOWN — could not run pip: {e}')
sys.exit(2)
if result.returncode != 0 or 'Name: litellm' not in result.stdout:
print('UNKNOWN — litellm package not found in this Python environment.')
print('If LiteLLM runs in a container, exec into it and re-run.')
sys.exit(2)
version_match = re.search(r'^Version:\s*(.+)$', result.stdout, re.MULTILINE)
if not version_match:
print('UNKNOWN — could not parse litellm version from pip output.')
sys.exit(2)
version_str = version_match.group(1).strip()
try:
installed = parse_version(version_str)
except (ValueError, IndexError):
print(f'UNKNOWN — unparseable version string: {version_str}')
sys.exit(2)
print(f'Installed litellm version: {version_str}')
print(f'Fixed in: {".".join(str(x) for x in FIXED_VERSION)}')
if installed < FIXED_VERSION:
print(f'VULNERABLE — litellm {version_str} is affected by CVE-2026-35029.')
print('Action: upgrade to >= 1.83.0 (recommend 1.83.9+ for full hardening).')
sys.exit(1)
else:
print(f'PATCHED — litellm {version_str} includes the fix for CVE-2026-35029.')
sys.exit(0)
if __name__ == '__main__':
main()