LiteLLM 1.107.0: A Release Pipeline Taken Over, a Stealer That Runs on Every Python Start
Updated 2026-10-28LiteLLM 1.107.0: A Release Pipeline Taken Over, a Stealer That Runs on Every Python Start
LiteLLM is the proxy a great many AI apps put between themselves and their model providers; its database holds the provider keys for every model it fronts. On October 21, 2026, its release pipeline published a version that steals exactly those.
The timeline, from LiteLLM's own report, all UTC:
- 10:08:29 GitHub branch protection rejects an unauthorised change to the private release workflow.
- 10:08:34 Five seconds later a privileged developer credential, belonging to an organisation owner, disables the protection and applies the change.
- 10:46 A staging run builds from an attacker-controlled lookalike repository,
Berri-AI/litellm. - 11:11 A second developer credential satisfies the production approval gate.
- 11:39 to 11:40 Seven malicious
litellm==1.107.0wheels upload to PyPI. - 11:46 Container jobs publish the Docker image;
v1.107.0,latest,main-latestandmain-stableall point at it. - 11:53 A third developer credential deletes the production and staging workflow records.
- 13:23 PyPI removes the release. Docker Hub tags are repointed by 14:20.
The official v1.107.0 source tag in GitHub never contained the malicious files. The artefacts did.
If you installed it, read this first
LiteLLM's instructions, in their order:
- Do not run
pip installfirst. The payload reruns on every Python start, and pip is a Python start. - Remove the persistence. In every affected site-packages:
cook.pth,cook.py,sitecustomize.py, and the matching__pycache__/cook*.pycandsitecustomize*.pyc. - Kill the daemon. A detached Python process holds
/tmp/remote_code_loader.lock. - Rebuild. Pin
litellm==1.106.2at minimum; LiteLLM recommends rebuilding images and virtualenvs from scratch. - Assume exfiltration if the host had outbound internet. A marker file can confirm it; its absence proves nothing.
- Rotate everything the host could reach: 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 the environment of any process on the host. - Audit. CloudTrail for
GetCallerIdentityfrom the instance role around install time, and for use of those credentials from outside your infrastructure.
Independent analysis of the wheels adds what the postmortem leaves out: the stealer collects SSH private keys, AWS, GCP and Azure credentials, browser passwords, and the configuration and token files of more than twenty AI coding tools, and posts the encrypted bundle to a host named to look like LiteLLM's own infrastructure.
PreFlight's Compromised Packages probe now reads requirements*.txt, poetry.lock, uv.lock and Pipfile.lock and flags litellm at 1.107.0, and at 1.82.7 and 1.82.8 from the March 2026 incident on the same package.
How the attacker got in
Three sets of developer GitHub CLI credentials. LiteLLM found an unexpected user account on an internal deployment that was exposed to the internet and believes the OAuth tokens were lifted from that deployment's logs. The report notes that a coding agent can embed a user's GitHub CLI token in a response body, and response bodies get logged.
Read that twice. The credentials that signed a malicious release were not phished and not guessed. They were in a log file of an LLM proxy, because something that talked to the proxy had a token in its context and the proxy logged what it saw. The March incident had already made LiteLLM harden its CI; this one went through the hardened pipeline on legitimate credentials, each gate satisfied by a different stolen token.
What this has in common with the npm worms
The same lesson as the August keyv wave, in a different ecosystem: the persistence outlives the package. pip uninstall litellm leaves sitecustomize.py in place, and Python imports sitecustomize on every start without being asked. The npm worms used a Claude Code SessionStart hook for the same effect. The mechanism is always something the host runs automatically, and the response always starts with removing that, not with rotating keys from the infected machine.
The lesson
Two, really. First: a proxy that holds every provider key is the highest-value box in the architecture, and its logs are part of that box. Scrub tokens before they land in a log, or do not log bodies. Second: pin and verify. A requirements.txt with litellm>=1.100 would have pulled 1.107.0 in the window; a lockfile with a hash would not have, and would have failed loudly on the rebuilt wheel. PreFlight reports the exact pin; the lockfile is what keeps the pin honest.
RELATED PROBES
- · Compromised Packages
- · Secret Scanner