AI SECURITY

LiteLLM CVE-2026-42271: Patch, Rotate, and Harden the RCE

CVE-2026-42271 is a command injection flaw in LiteLLM's MCP test endpoints. Chained with the Starlette host-header bypass (CVE-2026-48710), it becomes unauthenticated remote code execution. The fix: upgrade to LiteLLM 1.83.7 and Starlette 1.0.1, then rotate every credential the gateway touched.

June 16, 2026
11 min read
AI Security, LiteLLM, MCP
TL;DR
  • The chain: CVE-2026-42271 (command injection, CVSS 8.7) plus CVE-2026-48710 (Starlette host-header bypass, CVSS 6.5) equals unauthenticated RCE on the LiteLLM proxy. CISA added it to the Known Exploited Vulnerabilities catalog on June 9, 2026.
  • Affected: LiteLLM 1.74.2 through 1.83.6, and Starlette 0.8.3 through 1.0.0. Fixed in LiteLLM 1.83.7 and Starlette 1.0.1.
  • The fix: upgrade both packages, restart the proxy, and confirm the new versions are live.
  • The step people skip: if you were exposed, rotate every provider key, the master key, and the database credentials. Patching does not un-leak a secret an attacker already read.

What Is CVE-2026-42271 and Why It Hit CISA's KEV List

CVE-2026-42271 is a command injection vulnerability in LiteLLM, the most widely deployed open-source AI model gateway. It carries a CVSS score of 8.7. The flaw lives in two endpoints meant to preview an MCP server before you save it: POST /mcp-rest/test/connection and POST /mcp-rest/test/tools/list. Both accepted a full server configuration in the request body, including the command, args, and env fields that the stdio transport uses.

Here is the problem. To "test" an MCP server over stdio, LiteLLM spawned the supplied command as a subprocess on the proxy host. No sandbox, no allowlist. Send a config whose command is your own binary and the proxy runs it for you. That turns a convenience feature into arbitrary code execution as the LiteLLM process.

CISA added CVE-2026-42271 to its Known Exploited Vulnerabilities catalog on June 9, 2026, citing confirmed active exploitation in the wild (Help Net Security, June 9 2026). A KEV listing is not a theoretical advisory. It means attackers are already using it, and for US federal agencies it triggers a mandatory remediation deadline. If you run LiteLLM in production, treat this as an incident, not a backlog item.

The two-incidents pattern

This is LiteLLM's second critical incident in three months. In March 2026, a poisoned dependency in the install path exfiltrated credentials from affected deployments (Snyk). The June RCE is a different class of bug, but the lesson is the same: an AI gateway holds every key you own, so it deserves the same paranoia as a secrets vault.

How the Exploit Chain Reaches Unauthenticated RCE

On its own, CVE-2026-42271 requires a valid API key. It is "authenticated" RCE: bad, but it assumes the attacker already holds a low-privilege key. The reason this story jumped from advisory to active exploitation is the second link in the chain.

CVE-2026-48710, nicknamed "BadHost," is a host-header parsing flaw in Starlette, the ASGI framework LiteLLM is built on (CVSS 6.5). By appending characters like ? or # to the Host header, an attacker makes the framework compute the request path as / (a public route) while the router still dispatches to the real administrative endpoint. Path-based auth middleware checks the "public" path and waves the request through. The flaw affects Starlette 0.8.3 through 1.0.0 and reaches far beyond LiteLLM, into FastAPI, vLLM, and any ASGI app with path-based auth (CSO Online).

Stack the two together and the auth requirement disappears. The Starlette bypass gets an unauthenticated request past the middleware to the MCP test endpoint; the command injection then runs code. Horizon3.ai published the full chain with a working proof-of-concept, demonstrating unauthenticated RCE with no login required (Horizon3.ai). That is why a CVSS 8.7 bug effectively behaves like a 10.0 when both are present.

The chain in one line

Starlette BadHost (skip auth) → reach /mcp-rest/test/connection → supply a malicious stdio command → proxy spawns it → code runs as the LiteLLM process. Break any single link and the chain fails, which is why patching both packages matters more than patching either one.

Is My LiteLLM Proxy Vulnerable? How to Detect Exposure

You are vulnerable if you run LiteLLM 1.74.2 through 1.83.6 with the proxy reachable by untrusted clients. Start with the version check, then confirm whether the test routes are actually exposed, then go hunting in your logs.

Step 1 - check the installed version.

bashterminal
# Direct pip install
pip show litellm | grep -i version

# Or ask the package itself
python -c "import litellm; print(litellm.__version__)"

# Running in Docker? Check the pinned tag
docker inspect ghcr.io/berriai/litellm:main-latest --format '{{.Config.Image}}'

If the version sits anywhere in the 1.74.2 to 1.83.6 range, you are running affected code. The fix landed in 1.83.7.

Step 2 - confirm whether the test routes are reachable. The danger is highest when the proxy is internet-facing. A quick probe from outside your network tells you what an attacker sees.

bashterminal
# A 401/403 means auth is in front of the route (still patch, but lower urgency).
# A 200 or a 422 validation error means the route is processing your body. Patch now.
curl -s -o /dev/null -w "%{http_code}\n" \
  -X POST https://your-litellm-host/mcp-rest/test/tools/list \
  -H "Content-Type: application/json" \
  -d '{}'

Step 3 - hunt your access logs. Look for POSTs to either test endpoint, and pay attention to odd Host headers (a sign of the BadHost bypass) and any payloads carrying command or env values.

bashterminal
# Grep an nginx-style access log for hits on the vulnerable routes
grep -E "POST /mcp-rest/test/(connection|tools/list)" /var/log/nginx/access.log

# Flag requests with suspicious Host headers (BadHost uses ? or # in the host)
grep -E 'Host:[^"]*[?#]' /var/log/nginx/access.log

runZero published guidance on fingerprinting LiteLLM proxies across a fleet if you need to find every instance, not just the one you know about (runZero). Treat any log hit during the active-exploitation window as a confirmed compromise and move straight to credential rotation.

How to Fix LiteLLM CVE-2026-42271 (Upgrade Path)

The real fix is two upgrades, not one. Bring LiteLLM to 1.83.7 or later and Starlette to 1.0.1 or later. Patching LiteLLM closes the command injection; patching Starlette closes the auth bypass that makes it unauthenticated. Pin both so a future rebuild does not quietly downgrade you.

Step 1 - upgrade the packages.

bashterminal
# pip install
pip install --upgrade "litellm>=1.83.7" "starlette>=1.0.1"

# Confirm both landed
python -c "import litellm, starlette; print('litellm', litellm.__version__, '| starlette', starlette.__version__)"

Step 2 - pin the versions so they survive the next deploy.

textrequirements.txt
litellm>=1.83.7
starlette>=1.0.1

Step 3 - if you run the Docker image, bump the tag and rebuild rather than upgrading inside a running container.

dockerfileDockerfile
# Pin to a release that includes the fix, not a floating tag
FROM ghcr.io/berriai/litellm:v1.83.7

# If you maintain your own image, force the patched deps
RUN pip install --no-cache-dir "litellm>=1.83.7" "starlette>=1.0.1"

Step 4 - restart and verify the fix. After the restart, re-run the probe from the detection section. A patched proxy rejects the unauthenticated request to the test route instead of processing the body.

bashterminal
# Restart the service (systemd example)
sudo systemctl restart litellm

# Re-probe: a patched server should NOT return 200 for an unauthenticated test call
curl -s -o /dev/null -w "%{http_code}\n" \
  -X POST https://your-litellm-host/mcp-rest/test/tools/list \
  -H "Content-Type: application/json" -d '{}'

If you genuinely cannot upgrade this minute, the stopgap is to block the /mcp-rest/test/ routes at your reverse proxy and restrict admin access to trusted networks. That buys time. It does not remove the flaw, and it does nothing about credentials that may already be gone.

Why Patching Is Not Enough: Rotate Compromised Credentials

This is the step nearly every news article skips, and it is the one that actually protects you. RCE means an attacker could run code as the LiteLLM process, which means they could read environment variables, your config.yaml, and the database the proxy talks to. Upgrading stops the next attacker. It does not invalidate a secret a previous attacker already copied. If your proxy was exposed during the active-exploitation window, assume every secret it could see is now public.

A LiteLLM gateway is the worst possible thing to have compromised because it concentrates every downstream credential in one place. Rotate all of them, in roughly this order:

Credential rotation checklist
  1. Provider API keys. Every key the gateway routes to: OpenAI, Anthropic, Azure OpenAI, AWS Bedrock, Google Vertex, and any others. Revoke first, then issue new ones.
  2. The LiteLLM master key. The LITELLM_MASTER_KEY mints virtual keys, so a leaked master key undermines every key you have issued.
  3. Virtual / team keys. Reissue the per-team and per-user keys minted through the proxy. Do not assume low-privilege keys are harmless.
  4. Database credentials. The Postgres connection string and any cache (Redis) credentials in the environment.
  5. Anything else in the environment. Webhook secrets, SSO client secrets, observability tokens. If it was in the process environment, rotate it.

Partial rotation is a trap. Rotating the provider keys but leaving the master key alone means the attacker can mint fresh virtual keys at will. The March 2026 supply-chain incident already proved that LiteLLM credential exfiltration happens at scale, so this is not a hypothetical. Rotate the full set, then watch provider billing dashboards for anomalous usage over the following days.

Hardening MCP Endpoints Against Subprocess Attacks

Patching fixes this bug. Hardening fixes the class of bug. The architectural mistake here was a preview endpoint that spawned a user-supplied configuration as a subprocess. That pattern shows up across MCP tooling, so the defenses below apply well beyond LiteLLM.

Restrict admin and MCP routes by network. The proxy should not expose its admin surface to the public internet. Put it behind an allowlist so only trusted networks can reach the management and MCP routes.

nginxnginx.conf
# Allow LLM completions to everyone, but lock down admin + MCP routes
location ~ ^/(mcp-rest|ui|key/generate) {
    allow 10.0.0.0/8;       # internal network only
    allow 203.0.113.10;     # admin jump host
    deny all;
    proxy_pass http://litellm_upstream;
}

Run the proxy with least privilege. If RCE happens again, an unprivileged container with a read-only filesystem and no shell binaries limits the blast radius. The attacker lands in a box that cannot write, cannot spawn a shell, and cannot reach the rest of your network.

yamldocker-compose.yml
services:
  litellm:
    image: ghcr.io/berriai/litellm:v1.83.7
    user: "10001:10001"          # non-root
    read_only: true              # read-only root filesystem
    cap_drop: ["ALL"]            # drop all Linux capabilities
    security_opt: ["no-new-privileges:true"]
    tmpfs: ["/tmp"]              # writable scratch only where needed
    # Strict egress: only let the proxy reach the provider APIs it actually uses

Use least-privilege keys and prune unused ones. Issue virtual keys with the minimum scope each caller needs, and revoke keys for low-trust internal users until you have confirmed the upgrade. The fewer valid keys exist, the smaller the authenticated attack surface.

The general takeaway: any endpoint that turns user input into a spawned process must be sandboxed or removed. This is the same execution-boundary problem I wrote about in the MCP code execution pattern guide, and it is the same instinct behind hardening AI agents in CI/CD against prompt injection. Treat the gateway as untrusted-input-facing infrastructure, because it is.

Should You Still Trust LiteLLM?

Two critical incidents in three months is a fair reason to pause. My honest take: LiteLLM is still usable, but only if you stop treating it like a harmless proxy and start treating it like the high-value target it is. It is the most popular open-source AI gateway, and popularity buys it both more attacker attention and a maintainer team that ships fixes quickly. The June flaw was patched, and the broader Starlette bug was patched upstream within a day of public disclosure.

The real failure in most exploited deployments was not running LiteLLM. It was running it internet-facing with admin routes open and provider keys one RCE away from the public. The same gateway behind a network allowlist, running unprivileged, with scoped keys and a patch cadence, is a reasonable thing to operate. I run MCP servers in production myself, including the Jenkins MCP server, and the lesson is consistent: the danger is rarely the tool, it is the deployment.

If you cannot commit to a fast patch cadence and network isolation, that is a real signal that a direct-exposed gateway is the wrong shape for your team. Defense in depth, not abandonment, is the answer for everyone else.

Frequently Asked Questions

Patch, then harden

Upgrade LiteLLM to 1.83.7 and Starlette to 1.0.1 today, rotate your gateway credentials if you were exposed, and move the admin routes behind a network allowlist. For the official advisory and disclosure timeline, start with LiteLLM's security notes and the Horizon3.ai writeup.

Related Articles

MCP Architecture
MCP Code Execution Pattern
The execution-boundary model that this exploit abuses, explained hands-on.
AI Security
Harden AI Agents in CI/CD
Prompt-injection defenses for Claude Code and friends in GitHub Actions.
MCP Server
Jenkins MCP Server
A production MCP server for Jenkins CI/CD, built with the same paranoia.