← Back to Feed CACHED · 2026-10-14 13:24:48 · CACHE_KEY CVE-2026-35029
CVE-2026-35029 · CWE-863 · Disclosed 2026-04-06

LiteLLM AI Gateway Privilege Escalation via Unrestricted /config/update Endpoint

ASSESSED — NOISGATE
Vendor
—
—
—
Reassessed
—
—
—
Verdict: —
Do you agree?
01 · The Real Story

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.

"Auth-gated config endpoint chains to RCE on your LLM key vault — and attackers are already scanning for it."
02 · The Attack Path

5 steps from start to impact.

STEP 01

Obtain a valid API key

The attacker needs any valid LiteLLM API key — even one scoped to 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.
Conditions required:
  • Network access to the LiteLLM proxy (port 4000 by default)
  • A valid API key of any privilege level
Where this breaks in practice:
  • 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
Detection/coverage: Nuclei template available (pentest-tools.com scanner). GreyNoise/Shodan queries for litellm on port 4000 identify exposed instances.
STEP 02

POST to /config/update — rewrite environment variables

The attacker sends a crafted JSON payload to 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).
Conditions required:
  • Valid API key from Step 1
Where this breaks in practice:
  • None — the endpoint accepts any authenticated caller without further checks
Detection/coverage: WAF rules keyed on POST /config/update with non-admin bearer tokens. Application logs show config mutations by non-admin users — alert on any /config/update call.
STEP 03

Exfiltrate secrets via UI_LOGO_PATH arbitrary file read

The attacker sets 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.
Conditions required:
  • Successful config update from Step 2
Where this breaks in practice:
  • Container filesystem isolation may limit readable paths — but /app/.env is the primary target and is always present
Detection/coverage: Monitor /get_image requests for non-image content types. File integrity monitoring on the LiteLLM config file detects UI_LOGO_PATH tampering.
STEP 04

Admin account takeover via credential overwrite

The attacker overwrites 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.
Conditions required:
  • Successful config update from Step 2
Where this breaks in practice:
  • SSO-based admin auth (if configured) is not overridden by env vars — but most self-hosted deployments use the built-in username/password
Detection/coverage: Dashboard login anomalies (new IP, credential change events). Alert on UI_USERNAME or UI_PASSWORD in config update payloads.
STEP 05

Remote code execution via malicious pass-through handler

The attacker registers a custom pass-through endpoint handler that points to attacker-controlled Python code. LiteLLM executes this code via 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.
Conditions required:
  • Successful config update from Step 2
  • Attacker-hosted Python payload reachable from the LiteLLM container
Where this breaks in practice:
  • Egress filtering or network policies may block the container from reaching attacker-controlled endpoints
  • Container runtime security (Falco, Sysdig) may detect unusual process execution
Detection/coverage: Runtime security agents detect exec() calls with external code. Network monitoring flags outbound connections from the LiteLLM container to unknown hosts.
03 · Compensating Control

1
HIGH 8.3→IGNORE 0.0
SEVERITY REDUCED
Upgrade to LiteLLM v1.83.9+ immediately — The definitive fix. v1.83.0 adds 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.
2
HIGH 8.3→HIGH 7.5
Rotate the master key away from sk-1234 and enforce unique keys — Replace the default master key with a cryptographically random value. Audit all issued API keys; revoke any that are unused or over-privileged. This breaks the most common attack entry point (default credentials). Deploy within 30 days per noisgate mitigation SLA.
3
HIGH 8.3→MEDIUM 6.5
SEVERITY REDUCED
Place LiteLLM behind a VPN or zero-trust gateway — Remove direct internet exposure. Restrict access to authenticated internal users via VPN, Cloudflare Access, Tailscale, or equivalent. This eliminates the unauthenticated external attacker population entirely. Deploy within 30 days per noisgate mitigation SLA.
4
HIGH 8.3→LOW 3.0
SEVERITY REDUCED
Block /config/update at the reverse proxy layer — Add a WAF or reverse proxy rule (nginx, Envoy, Traefik) that returns 403 for any request to /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.
5
HIGH 8.3→MEDIUM 5.5
SEVERITY REDUCED
Deploy container runtime security (Falco/Sysdig) and egress filtering — Runtime security detects anomalous 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.
What doesn't work
  • 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/update path.
04 · Intelligence Metadata

The supporting signals.

In-the-wild exploitationActive. 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-conceptPublic. 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.
EPSS3.982% (91st percentile) — indicates notably elevated exploitation probability relative to the general CVE population.
CISA KEVNot listed as of 2026-10-14. Given active exploitation evidence, KEV addition would not be surprising.
CVSS vectorCVSS: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 versionsAll 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 versionv1.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 dataWiz 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 & creditDisclosed 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 CVEsCVE-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.

  1. GitHub Advisory — GHSA-53mr-6c8q-9789
  2. Check Point Research — LiteLLM Gateway Vulnerabilities
  3. Wiz — Breaking LiteLLM: From Auth Bypass to Cloud Compromise
  4. SecurityOnline — CVE-2026-35029 Exploited for Full Server Takeover
  5. LiteLLM Vendor Advisory — Security Hardening April 2026
  6. PoC Repository — learner202649/CVE-2026-35029-PoC
  7. CyberNews — Thousands of LiteLLM Instances Exposed
  8. Pentest-Tools — LiteLLM Arbitrary File Read Scanner
05 · The Call

Final Verdict
= UNCHANGED to HIGH (8.3/10)

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-1234 master 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.

06 · Verification

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.

noisgate-verify.py
PYTHONREAD-ONLYSAFE
#!/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()