LiteLLM 1.107.0 on PyPI and Docker carried a credential stealer
An attacker drove LiteLLM's own release pipeline with stolen GitHub tokens; pin 1.106.2, check for three dropped files and rotate keys.
An attacker used LiteLLM's own release pipeline to publish a credential-stealing version 1.107.0 of the popular AI gateway library to PyPI and its Docker images on Wednesday (Oct. 21), LiteLLM said.
The bad package was on PyPI from 7:39 to about 9:23 a.m. ET. The Docker Hub tags v1.107.0, latest, main-latest and main-stable pointed to the poisoned image from 7:46 to 10:20 a.m. ET, and the GitHub Container Registry copies until about 9:51 a.m., according to LiteLLM.
"If 1.107.0 was ever installed on a host with outbound internet, assume the exfil succeeded," LiteLLM said in its incident post, which lists its investigation as still in progress.
No one has published how many hosts installed 1.107.0 or pulled the bad images. LiteLLM also hasn't confirmed how the attacker got into an internal deployment, saying only that it "currently suspect[s]" a "recently patched vulnerability."
What the malware does
Each wheel drops cook.pth, cook.py and sitecustomize.py into site-packages. "Both run when any Python process starts on the host, even one that never imports litellm," security firm SafeDep said in a writeup discussed on Hacker News. That includes running pip.
The stealer takes SSH keys, cloud credentials, CI secrets, browser passwords, AI coding-tool tokens and the LLM provider keys stored in a LiteLLM proxy's database, according to Wiz and SafeDep. sitecustomize.py is an hourly backdoor that can download and run remote code, though Wiz and Datadog said no second-stage payload was observed.
Wiz said it "has observed abuse of stolen credentials, starting approximately 4.5 hours post-exfiltration," including AWS credentials probed for Bedrock access. That hasn't been independently confirmed.
The attacker didn't bypass LiteLLM's hardened pipeline but drove it, using three developers' stolen GitHub CLI tokens to override branch protection, approve the release and delete workflow records. It pointed the build at a lookalike repo, Berri-AI/litellm, LiteLLM said.
LiteLLM believes the tokens came from logs of an internet-exposed internal deployment. It said it has seen "specific situations in which Claude Code will embed a user's GitHub CLI OAuth token into a response body." Anthropic hasn't publicly commented, and no one has published a reproduction.
The release shipped "with seemingly legitimate build provenance that faithfully recorded the malicious fork as the source," Datadog Security Labs said.
Am I affected, and what should I do?
You're affected "if you used an unpinned version of LiteLLM between 11:39 and 13:23 UTC via pip or if you used the docker image v1.107.0, latest, main-latest, or main-stable between 11:46 and 14:20 UTC," LiteLLM said. That's 7:39 to 9:23 a.m. ET for pip and 7:46 to 10:20 a.m. ET for Docker.
LiteLLM says "all previous versions are safe" and recommends pinning litellm==1.106.2, which is now the latest version on PyPI. The Upwind researchers who reported the attack in issue #47826 said every 1.106.2 wheel checked clean.
LiteLLM suggests pip show litellm to check, but on a suspect host that command starts Python and reruns the stealer, so check the filesystem from the shell first:
find / \( -name 'litellm-1.107.0.dist-info' -o -name 'cook.pth' -o -name 'cook.py' -o -name 'sitecustomize.py' \) -path '*site-packages*' 2>/dev/null
ls -la /tmp/.pc_once_72129118c59f5636c0bb /tmp/remote_code_loader.lock 2>/dev/null
docker images --digests | grep -i litellm
- Check Docker digests. Treat any container that ran image index
sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339eas compromised, per LiteLLM. On GHCR, thelitellm-databaseandlitellm-non_rootindexes beginsha256:c00f9d92c427andsha256:7b00e91cd2fe. - Check lockfiles and Oct. 21 CI logs for
litellm1.107.0. Any unpinned dependency that resolved during the window could have pulled it. - Clean up from the shell, before running Python. Delete the three files and their
.pycfiles from every affectedsite-packages(asitecustomize.pywith nocook.pthbeside it may be legitimate), and kill the detached Python process holding/tmp/remote_code_loader.lock. - Rebuild venvs and images from scratch pinned to
litellm==1.106.2, and pin Docker images by digest. - Rotate from a clean machine: the instance or task IAM role, every provider key in the LiteLLM proxy database plus master and virtual keys, the
DATABASE_URLpassword, and any secret in a process environment on the host. - Check CloudTrail for
GetCallerIdentitycalls from the instance role around install time, then for use of its credentials from outside your infrastructure.
If the /tmp/.pc_once_… marker exists, the exfiltration is confirmed, LiteLLM said, but its absence "proves nothing" because cleanup can remove it.
This is LiteLLM's second PyPI compromise this year. Versions 1.82.7 and 1.82.8 carried a credential stealer on March 24, LiteLLM said, and no connection between the two attacks has been established, according to Datadog. LiteLLM has paused regular releases while it investigates, it said in issue #47826.