TL;DR: LiteLLM 1.107.0, the Python SDK and proxy that puts many AI model providers behind one API, was published to PyPI and Docker on October 21, 2026 with a credential stealer inside. The issue’s reporter and StepSecurity say the malware runs on every Python start in an environment where 1.107.0 is installed, even if nothing imports litellm; the reporter says it collects cloud, SSH and AI tool credentials, environment variables and the provider API keys stored in a LiteLLM proxy database. BerriAI, which maintains LiteLLM, says PyPI has quarantined 1.107.0 and the malicious Docker images have been removed, but it hasn’t yet found or locked down how the attacker published the release. If you installed 1.107.0 or pulled a LiteLLM image on October 21, treat that machine as compromised: clean it up, rebuild clean on 1.106.2 (or an earlier explicit version) and rotate every key it could reach.
What happened
Status as of Oct 21, 2026, 11:25 p.m. Manila (15:25 UTC): PyPI no longer serves 1.107.0, and its latest version is 1.106.2. BerriAI said at 14:32 UTC (10:32 p.m. Manila) that “the malicious docker images have been removed” and that its next update is at 16:30 UTC (12:30 a.m. Manila on October 22). BerriAI didn’t say which tags were affected; StepSecurity says the latest, main-latest and main-stable tags pointed to the infected image, alongside v1.107.0. When we checked Docker Hub’s tag list for litellm/litellm, v1.107.0, latest, main-latest and main-stable were no longer listed and v1.106.2 was. When we checked the GitHub Container Registry (GHCR), the v1.107.0, latest, main-latest and main-stable tags were not found for ghcr.io/berriai/litellm, litellm-database and litellm-non_root, while v1.106.2 was still available for all three. The issue’s title, set by the reporter before BerriAI’s 14:32 UTC statement, still says the Docker latest and main-stable tags are “STILL infected”; we’ve gone by BerriAI’s later statement and our Docker Hub and GHCR checks. This is a moving story; we’ll update it.
The compromise was reported at 12:06 UTC (8:06 p.m. Manila) in issue #47826 on BerriAI’s GitHub repository, by Lidor Machluf of the Upwind security research team. The issue and StepSecurity’s analysis describe the same chain of events (times UTC; in Manila, 8 hours ahead, it all fell between 7:39 and 10:32 p.m. on October 21):
- 11:39 to 11:40: 1.107.0 was uploaded to PyPI. All seven 1.107.0 wheels (macOS, Linux and Windows) carry three extra files,
cook.pth,cook.pyandsitecustomize.py, that pip installs into the root of site-packages. The source package (.tar.gz) has a tampered build config but not the payload files. - 11:48: StepSecurity says the infected image was pushed to Docker Hub, and the
latest,main-latestandmain-stabletags pointed to it. The issue’s reporter found the same payload files, byte-identical, in thev1.107.0images forghcr.io/berriai/litellm,litellm-databaseandlitellm-non_rootand indocker.io/litellm/litellm. StepSecurity says the floating tags pointed to the infected image “for about three hours.” - By 13:23: the reporter said PyPI had removed 1.107.0. At 13:50 UTC, BerriAI said: “We are actively investigating and treating this as SEV-0. PyPI quarantined 1.107.0.”
- 14:32: BerriAI said the malicious Docker images had been removed. “We have not yet identified or locked down the method by which the threat actor published the malicious release. This is where our current efforts are focused.”
How it got in: the payload isn’t in the v1.107.0 git tag. The reporter says the release was built from commits stacked on top of the tag in a lookalike repository, Berri-AI/litellm (with a hyphen), and StepSecurity says the build provenance attached to the v1.107.0 Docker images names that lookalike repository as the source. Neither BerriAI nor the reporter has said how the attacker got the release to build from it.
What the malware does, according to the reporter’s analysis of the decoded payload (they say nothing was executed):
- The reporter says
cook.pthmakescook.pyrun “on every start of that interpreter or venv,” andsitecustomize.py“also runs automatically at startup.” That includes running pip in that environment. cook.pyis a stealer that collects, among other things, SSH keys and shell histories; AWS, Azure, Google Cloud, Kubernetes, Docker and GitHub CLI credentials;.envfiles and private keys; CI and Vault secrets; “AI tool credentials and configs” for tools including Claude, Codex, Gemini, Cursor and Copilot; browser passwords and cookies; “the environment variables of every readable process”; and cloud instance credentials. IfDATABASE_URLis set, it dumps the LiteLLM proxy’s stored credentials and model tables, “i.e. every upstream provider key the proxy stores.” It encrypts the bundle and sends it tohttp://www.litellm.dev/healthcheck, which the reporter notes is not LiteLLM’s domain (litellm.ai).sitecustomize.pystarts a background process that checks a GitHub file every hour and, if it holds a domain, downloads and runs Python code from it. The reporter said that file was empty, so this stage was “dormant for now”; StepSecurity says the GitHub account behind it was later deleted. On Windows this part fails, butcook.pystill runs.
Why it matters
LiteLLM often sits in the middle of a team’s AI stack, holding the API keys for every model provider it routes to, on laptops, in CI and on production gateways. Researchers say the stealer runs at every Python start, so your code wouldn’t need to use litellm: installing it would be enough. StepSecurity notes that many projects depend on LiteLLM with an open-ended litellm>= constraint, so “a fresh install or lockfile refresh would have picked up 1.107.0,” and proxies that track the latest or main-stable image picked it up on their next pull or restart. It also says this is the second LiteLLM compromise on PyPI this year, after versions 1.82.7 and 1.82.8 in March.
What to do now
- Find out whether 1.107.0 ever reached you. Check lockfiles and requirements (
uv.lock,poetry.lock,requirements*.txt) for1.107.0, CI logs from October 21 for installs oflitellm-1.107.0, and any container that ran a LiteLLM image pulled on October 21 (v1.107.0,latest,main-latestormain-stable). On a machine, look in site-packages forcook.pth,cook.pyandsitecustomize.py. Do this from the shell: the reporter warns, “Don’t start withpip install,” because, the reporter says, any Python start in an affected environment runs the payload again. The marker file/tmp/.pc_once_72129118c59f5636c0bbmeans data was sent; if it’s missing, the reporter says “that proves nothing.” - If you were affected, clean up first. From the shell, delete
cook.pth,cook.pyandsitecustomize.py, plus any matching.pycfiles in__pycache__, from every affected site-packages, and kill the detached Python process holding/tmp/remote_code_loader.lock. The reporter lists deleting the files first; StepSecurity lists killing the process first. Both say rebuilding environments and images from scratch is better than cleaning in place. - Rebuild clean on 1.106.2 (or an earlier explicit version) and rotate every key. Don’t just change the version number on an affected machine: rebuild environments and images from scratch on 1.106.2 or an earlier explicit version, then rotate keys as in step 4. BerriAI says: “please pin your version to 1.106.2 or any explicit version published prior to now.” Both sources say to pin the
v1.106.2image by digest, not by a floating tag. StepSecurity says some PyPI mirrors kept serving cached 1.107.0 files after PyPI removed it, so purge 1.107.0 from any internal mirror, cache or registry. - Rotate everything the machine could reach. The reporter says that if 1.107.0 was ever installed on a host with internet access, “assume the exfil succeeded.” Rotate cloud keys and instance roles, SSH and GPG keys, GitHub, npm and PyPI tokens, CI and Vault secrets, AI tool tokens and saved browser passwords. On LiteLLM proxy hosts, rotate every provider API key stored in the proxy, the LiteLLM master and virtual keys, and the
DATABASE_URLpassword; StepSecurity adds the salt key. - Check your logs. The reporter suggests checking AWS CloudTrail for
GetCallerIdentitycalls from the instance role around install time, then for use of those credentials from outside your infrastructure. StepSecurity suggests searching network logs forlitellm.dev, for requests toraw.githubusercontent.comunder theletters9813account and for any path ending in/codepy, and blockinglitellm.dev.
LiteLLM’s enterprise customers who pull from its private registry aren’t affected, BerriAI says. For a way to stop brand-new package versions reaching CI automatically, see our story on GitHub’s package firewall and npm cooldowns; the same idea, waiting a few days before accepting a new release, would have kept 1.107.0 out of many installs.
What’s still unknown
BerriAI hasn’t said how the attacker got its release process to build from the lookalike repository and publish to PyPI and Docker, and says it hasn’t locked that path down yet. For the time being, it asks open-source users to pin 1.106.2 or another explicit version published before its statement. It also hasn’t said how many users installed 1.107.0, whether any stolen credentials have been used, or when the next release will come. BerriAI says it will post updates “every two hours.”
Sources & method
Sources
- BerriAI/litellm GitHub issue #47826, “[SECURITY] litellm 1.107.0 compromised …” (title shortened), opened Oct 21, 2026, 12:06 UTC, with BerriAI’s replies at 13:50 and 14:32 UTC
- litellm on PyPI
- StepSecurity, “litellm 1.107.0 Compromised on PyPI,” Oct 21, 2026
Method. Last checked October 21, 2026, at 11:25 p.m. Manila time (15:25 UTC). BerriAI’s statements come from its replies in the GitHub issue, posted by the GitHub account ojensen-berri, whose profile gives the name Oliver Jensen, the title “Director of Security at LiteLLM” and the company BerriAI; GitHub labels the account a contributor to the repository. PyPI’s current state comes from PyPI’s own project data. The payload behavior, affected files and images, remediation steps and the 11:39 and 13:23 UTC times come from the issue’s reporter; the Docker push time, the three-hour window, the mirror warning, the log searches and the March incident come from StepSecurity’s analysis. We did not download, install or run the affected package or images. The lockfile and CI checks and the cooldown suggestion are our own judgment. No affiliate links on this page. How we work.
Spotted an error? See our corrections policy and tell us.
![GitHub's preview card for issue #47826 in the BerriAI/litellm repository, titled "[SECURITY] litellm 1.107.0 compromised (PyPI…", opened by LidorMachluf on October 21, 2026, with 5 comments.](/images/articles/litellm-1-107-0-pypi-docker-credential-stealer-137eb305.png)


