LiteLLM Supply Chain Attack: 1.107.0 Shipped a Stealer
The LiteLLM supply chain attack put a credential stealer in 1.107.0 via an unrevoked master key. Check exposure, rebuild, pin 1.106.2, rotate secrets.
The LiteLLM supply chain attack put a credential stealer into litellm==1.107.0 on PyPI and into the latest, main-latest, main-stable and v1.107.0 Docker images on 21 October 2026. The malicious wheels were live from 11:39 to 13:23 UTC. The root cause was a master key leaked in May and never revoked. If any environment started Python with 1.107.0 installed, treat it as compromised: rebuild it, pin 1.106.2 and rotate every secret it could read.
What happened in the LiteLLM supply chain attack
LiteLLM is a widely used Python library and proxy that puts one API in front of many model providers. In practice it often sits on hosts that hold provider keys for OpenAI, Anthropic, AWS Bedrock and others, which is what made it a good target.
LiteLLM's root cause analysis, published on 23 October, traces the chain back five months:
- 27 May 2026. A configuration file committed to the public
LiteLLM-Labs/lite-harnessrepository contained the master key for a LiteLLM Agent Platform deployment. The commit was force-pushed over and the key was flagged for revocation, but it was never revoked. - 10 October, 21:13 to 21:28 UTC. The attacker used that key against the Agent Platform API. One response returned a GitHub CLI OAuth token belonging to an owner of the GitHub organization.
- 10 October, 22:11 to 22:14 UTC. With the owner's token, the attacker ran CI workflows on
BerriAI/litellmandBerriAI/litellm-autothat sent repository secrets to awebhook.siteendpoint. Two maintainer tokens were among them. A second round of exfiltration across private repositories followed on 12 October. - 21 October, 10:08 to 11:08 UTC. The attacker changed the release workflow in
BerriAI/project-releaserto build from a lookalike fork,Berri-AI/litellm, overriding branch protection. At 11:11 a stolen maintainer token approved the production gate. - 21 October, 11:39 to 11:46 UTC. Seven
litellm==1.107.0wheels went to PyPI, followed by images on Docker Hub and GHCR. Run records were then deleted andmainwas force-pushed to hide the workflow change.
A community member opened GitHub issue #47826 at about 12:06 UTC; The Hacker News credits Upwind researcher Lidor Machluf with the report. PyPI quarantined the release at 13:23 UTC, and the Docker Hub and GHCR tags were removed or repointed to clean images by about 14:20 UTC. LiteLLM says the official v1.107.0 source tag on GitHub does not contain the malicious files: the problem is in the published artifacts.
Who is affected
You are exposed if any of these is true for the window above:
- An install or upgrade of LiteLLM without a version pin ran between 11:39 and 13:23 UTC on 21 October and resolved to 1.107.0.
- A container was built or pulled from
ghcr.io/berriai/litellm,litellm-database,litellm-non_rootor the Docker Hub equivalents usinglatest,main-latest,main-stableorv1.107.0during roughly 11:46 to 14:20 UTC. - A CI job, notebook server or developer laptop resolved LiteLLM as a transitive dependency of another package during that window.
Environments pinned to an earlier explicit version, or images pinned by digest, did not pull the bad release. That is the strongest argument this incident makes for pinning Python dependencies with pip hash checking.
Technical analysis
LiteLLM's incident post lists the files the release dropped: cook.pth, cook.py, sitecustomize.py, their compiled __pycache__ copies, and the litellm-1.107.0.dist-info directory. The GitHub issue title describes them as a "cook.pth credential stealer" and a "sitecustomize RCE loader".
Both file types run automatically when the Python interpreter starts. A .pth file in site-packages can contain lines that Python executes during startup, and sitecustomize is a module the interpreter imports on its own. The result, per both LiteLLM and The Hacker News, is that the code runs even if nothing ever imports LiteLLM. That includes running pip itself. If this mechanism is new to you, read what a Python .pth file is and why attackers use it.
The Hacker News reports two components: one harvests credentials for developer tools, AI applications, cloud environments and browsers; the other is a Unix background process that periodically fetches and runs code supplied by the attacker. LiteLLM ties that daemon to the lock file /tmp/remote_code_loader.lock.
The chain also shows how far one key can reach. A single Agent Platform master key led to an owner-level GitHub OAuth token with no scope restriction, which led to every repository secret, which led to the release pipeline. Each hop used a legitimate credential, so none of it looked like an exploit. The same pattern drove the GhostAction campaign earlier this month.
What to do now
LiteLLM's guidance, in order:
- Find exposure. Run
pip show litellmin each environment and check image digests in your registry and deployment history. Search every site-packages directory and container layer forlitellm-1.107.0.dist-info,cook.pth,cook.pyandsitecustomize.py, and look for/tmp/remote_code_loader.lock. LiteLLM warns that finding none of these does not prove a host is clean. Some environments ship a legitimatesitecustomize.py, so compare against a known-good build. - Do not run pip first. Any Python start, including
pip install, reruns the malicious startup files. Delete the files from every affected site-packages directory and kill the detached Python process holding the lock file before touching anything else. - Rebuild, then pin. Reinstall with
litellm==1.106.2or another explicit version published before the incident. LiteLLM says rebuilding images and virtual environments from scratch is better than cleaning in place. - Assume exfiltration. If 1.107.0 ran on a host with outbound internet access, assume its secrets left. Rotate the instance or task IAM role, every provider key stored in the LiteLLM proxy database, the master and virtual keys, the
DATABASE_URLpassword and any secret present in the environment of any process on the host. - Check cloud logs. In AWS, look in CloudTrail for
GetCallerIdentitycalls from the instance role around install time, and for those credentials being used from outside your infrastructure.
Indicators worth adding to detection and blocking:
- Lookalike source repository
Berri-AI/litellm(the real one isBerriAI/litellm). - Attacker source commit
20535d8fa11f786a6c24df7488a0e449ed5f09adand workflow commit9cf97e935aeaf791b9c8db224a2bb3ee156134ce. - Malicious image index digest
sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e. - Per The Hacker News: the IP 69.48.229[.]143 used against the Agent Platform, the domain litellm[.]dev, a workflow file named
.github/workflows/cache.yml, the commit subject "ci: bump cache config" and branches namedci-tmp-<hex>.
If you maintain packages yourself, check your own organization for long-lived owner tokens and keys that were "removed" from a repository but never revoked. Our guide on why deleting a leaked API key from Git is not enough covers the process. LiteLLM was also the subject of an exploited MCP authentication bypass in September, so teams running the proxy should confirm they are on a current, clean release.
What to watch next
LiteLLM says it has locked its public registries, removed all members from its GitHub organization except one temporary owner, stripped GitHub permissions from the release workflow and is revoking every token tied to its internal systems and vendor platforms. It has promised to publish process changes. Watch for a fixed release and for any confirmed reports of stolen provider keys being used. The incident post itself notes that some of its early assumptions were wrong, so treat the attack-chain analysis as the current record.