CVE Tools
A LiteLLM Master Key Leaked in May. Nobody Revoked It. In October, It Hijacked a Release.. LiteLLM's second supply-chain compromise of 2026 traces back to a config file that was force-pushed over but

A LiteLLM Master Key Leaked in May. Nobody Revoked It. In October, It Hijacked a Release.

LiteLLM's second supply-chain compromise of 2026 traces back to a config file that was force-pushed over but never fully cleaned up — and a release-approval rule relaxed the same week.

On October 21, 2026, LiteLLM — the open-source LLM gateway built by BerriAI and run in production by companies including NVIDIA, Netflix, AT&T and Okta — shipped a credential-stealing backdoor as a routine PyPI release. It is the second time this has happened to LiteLLM in 2026. Our read: the proximate cause was a textbook release-pipeline hijack, but the root cause was a half-finished incident response from May — a master key the team said it would revoke and never did — compounded by a release-approval shortcut taken the very week the attack began. The lesson for anyone running LiteLLM isn't "rotate harder." It's that an incident isn't closed until every credential it touched is confirmed dead, not just flagged for later.

136 daysleaked master key sat unrevokedMay 27 → Oct 10, 2026
~2 hrsmalicious package stayed live11:39–13:23 UTC, Oct 21
7 + 4PyPI wheels and Docker/GHCR tags poisoned
2nd in 2026LiteLLM supply-chain compromise this yearafter March's TeamPCP/Trivy attack

The timeline

From a leaked config file to a poisoned release

  1. Master key leaks
    A config file (opencode.json) holding the LiteLLM Agent Platform master key is committed to the public repo LiteLLM-Labs/lite-harness. The team force-pushes over the commit and flags the key for revocation — but the key is never actually revoked.
  2. Key weaponized
    An attacker makes authenticated calls to the Agent Platform API using the leaked key. One call to /api/v1/managed_agents/agents returns a GitHub org owner's OAuth token — unscoped and not tied to a service account.
  3. Secrets exfiltrated, tracks covered
    Two throwaway branches on BerriAI repos run CI workflows that leak seven repo secrets — including two more maintainers' tokens — to a webhook.site endpoint. Both workflow runs are deleted minutes later.
  4. Branch protection overridden
    A commit rerouting the release build source is blocked once, then force-pushed through after the attacker disables branch protection with the stolen org-owner token.
  5. Lookalike repo signed and released
    A second stolen maintainer token approves a production release built from Berri-AI/litellm — a one-character typosquat of the real BerriAI/litellm.
  6. Malicious package goes live
    litellm==1.107.0 publishes to PyPI across all seven wheels; matching Docker Hub and GHCR image tags follow within minutes.
  7. Caught in under 20 minutes
    Independent researcher LidorMachluf publicly flags the compromise on GitHub issue #47826.
  8. Contained
    PyPI, GHCR and Docker Hub pull the artifacts. Total time live: roughly two hours.

A startup hook, not an import

The attacker didn't touch LiteLLM's actual application code. Three files — cook.pth, cook.py and sitecustomize.py — were planted in the package's site-packages directory. Python processes .pth files and imports sitecustomize automatically on every interpreter startup, before any application code runs. That meant simply running python or pip to inspect a poisoned install was enough to trigger the payload — importing litellm was never required.

  • Cloud and infrastructure credentials: AWS, Azure, GCP, Kubernetes and Docker
  • AI-specific secrets: coding-assistant auth files plus LiteLLM's own stored provider API keys and model configs
  • Developer secrets: Git, GitHub, npm, PyPI and CI/CD tokens, .env files, SSH/GPG/TLS keys
  • Browser data: saved logins, cookies, autofill and payment data
  • Host and runtime data: environment variables, shell history, system and network info

A corner cut the same week

The gap between "flagged" and "fixed"

What happened in May
  • Force-pushed over the exposed commit
  • Flagged the master key for revocation
  • Treated the exposure as handled
What full containment required
  • Actually revoke and rotate the master key
  • Audit everything the key could reach
  • Verify revocation before closing the incident

LiteLLM's second compromise this year

March 2026October 2026
ActorSelf-named "TeamPCP"Unidentified; used a leaked internal key
Entry vectorCompromised Trivy CI/CD scannerUnrevoked Agent Platform master key
Malicious versions1.82.7, 1.82.81.107.0
PayloadAWS/SSH/Kubernetes/DB credential harvesterCloud, AI, dev and browser credential stealer plus remote payload loader
Containment timePyPI quarantined within 46 minutes~2 hours across PyPI, Docker Hub and GHCR
Clean version to pin1.82.61.106.2

Two unrelated entry vectors, four and a half months apart, both ending the same way: a poisoned PyPI release reaching every environment that updated. That repetition is itself the story — AI-gateway libraries sit on the same trust path as the cloud and model-provider credentials they route, which is exactly what makes their release pipelines worth automating an attack against.

What to do if you run LiteLLM

  1. Don't run pip install or even a bare python command in a potentially affected environment — either can re-trigger the loader.
  2. Pin to litellm==1.106.2, ideally by digest, and rebuild virtual environments and containers from scratch rather than patching in place.
  3. Treat any host that ran 1.107.0 with outbound internet access as exfiltrated.
  4. Rotate everything the host could read: cloud IAM credentials, every provider API key stored in the LiteLLM proxy database, master and virtual keys, and the database password.
  5. Audit CloudTrail (or your cloud's equivalent) for GetCallerIdentity calls and other use of the credentials the host held.

Data as of October 25, 2026

Sources: LiteLLM's canonical incident report and attack-chain writeup, the original disclosure thread on GitHub (BerriAI/litellm issue #47826), Microsoft's independent technical analysis of the Python startup-hook mechanism.