Poisoned LiteLLM 1.107.0 stole cloud and AI keys on every Python start
On 21 October 2026 a poisoned LiteLLM 1.107.0 release went out through the project's own signed release pipeline. For about two hours, every Python start on an affected machine could leak cloud credentials, AI tool tokens and the LLM provider keys stored in a LiteLLM proxy.

On 21 October 2026, LiteLLM, one of the most widely used building blocks in AI engineering, shipped malware to its own users. Version 1.107.0 of the Python package appeared on PyPI and in the project's official Docker images with a hidden credential stealer and a remote code loader built in. The release came out of LiteLLM's real release pipeline, carried its real signatures and was live for about two hours before it was pulled.
LiteLLM is the library many teams put between their code and the large language model providers. It offers one interface for OpenAI, Anthropic, Google, AWS Bedrock and dozens of other APIs, and its proxy server acts as a central AI gateway that holds the provider keys for a whole company. Security firms Datadog and Socket put its download count at about 23 million per week. That makes it exactly the kind of package an attacker wants: wherever it runs, valuable keys are close by.
This article explains what happened, who is affected, what the malware took, how the attacker got in, and what teams should do now. It is the second LiteLLM supply chain compromise this year, and the way the attacker entered says a lot about the new risks of AI coding tools.
The short version
- A malicious `litellm==1.107.0` was on PyPI from 11:39 to 13:23 UTC on 21 October, in all seven wheels for Linux, macOS and Windows.
- The Docker tags `v1.107.0`, `latest`, `main-latest` and `main-stable` on Docker Hub and GHCR pointed to infected images from 11:46 UTC until 13:51 (GHCR) and 14:20 (Docker Hub).
- According to Wiz, citing ClickPy data, the malicious version was downloaded about 49,000 times.
- The malware ran at every Python start on an infected machine, even in processes that never import LiteLLM.
- It collected cloud credentials, SSH keys, AI coding tool tokens, browser passwords and the provider API keys stored in a LiteLLM proxy database, then sent them to a lookalike domain.
- The last safe version is 1.106.2. Release candidates 1.107.0rc1 and rc2 are also clean. Enterprise customers on LiteLLM's private registry were not affected.
Four hours that matter
The attack followed a tight schedule. LiteLLM's own incident report, written by CEO Krrish Dholakia, CTO Ishaan Jaffer, security director Oliver Jensen and engineer Nate Armstrong, lays out the timeline in detail.

At 10:08 UTC, GitHub's branch protection correctly rejected an unauthorized change to LiteLLM's private release workflow. Five seconds later, a credential belonging to a privileged developer account was used to override that protection and push the change anyway. At 10:46 the modified workflow started a staging run, but instead of building from the real `BerriAI/litellm` repository, it pulled code from `Berri-AI/litellm`, a lookalike with a single extra hyphen that the attacker controlled.
At 11:11 a second developer account approved the production gate. At 11:39 the seven poisoned wheels landed on PyPI, and seven minutes later the infected container images followed. At 11:53 a third account deleted the workflow records, which removed logs that investigators would have needed. By 12:24 the workflow had been restored to its previous version, PyPI removed the release by 13:23, and the last Docker Hub tags were fixed at 14:20.
The exposure was not the same on every channel. Pinned installs of older versions were never touched. The risk was concentrated on anyone who installed LiteLLM without a pinned version in that window, or who pulled one of the moving Docker tags such as `latest`.

Two hours sounds short. In modern infrastructure it is not. CI pipelines rebuild containers on every commit, autoscaling groups pull `latest` when they start new nodes, and developers run fresh installs all day. That is how a two hour window turns into tens of thousands of downloads.
How the malware worked
The analysis from SafeDep shows how small the visible change was. The source package had a single extra line in its build settings, `data = "cook"`, which told the build tool to copy a hidden `cook` folder into the wheel. Installing the wheel dropped three files directly into Python's `site-packages` folder: `cook.pth`, `cook.py` and `sitecustomize.py`.
Both mechanisms abuse normal Python features. Python reads every `.pth` file in `site-packages` at startup and runs lines that begin with `import`. The file `cook.pth` contained just `import cook`. Python also imports a module named `sitecustomize` automatically if one exists. The result: any Python process on the machine ran the malware, whether it was the AI application itself, a test run, an IDE language server or even `pip`. Wiz says this combination of both tricks at once appears to be the first documented case in the wild.
The first payload, `cook.py`, is a stealer that calls itself "privcollect". It runs 16 collection modules, encrypts what it finds with AES 256 and a wrapped RSA 4096 key, and sends it to `www.litellm[.]dev/healthcheck`, a domain chosen to look like LiteLLM's own. It then writes a marker file so it only collects once per host.

The target list is a map of what a modern AI developer machine holds. There are the classic cloud and SSH secrets, but also a dedicated module for AI coding tools: configuration and tokens for Claude Code, Claude Desktop, Cursor, Windsurf, Copilot, Gemini CLI, Codex, Aider and others, plus MCP configuration files. One module goes straight for LiteLLM's own crown jewels. It reads `DATABASE_URL` and dumps the tables where a LiteLLM proxy stores the API keys for every model provider it routes to. For a company that uses LiteLLM as its central gateway, that can mean the keys to all of its AI spending at once.
The second payload, `sitecustomize.py`, is a backdoor. It detaches from its parent process and wakes up every hour. Each time, it reads a server address from a file in a GitHub repository, runs the stealer again and downloads and executes whatever code that server offers. The design gave the attacker a way to push new code to every infected host just by editing one text file.
According to SafeDep and Wiz, that GitHub account was taken down within about two hours, and the address file never held more than test values. The backdoor is therefore dormant on most machines. That is good news, but it does not undo what the first payload already sent out.
The stolen keys were used within hours
Wiz reports that the attacker started testing stolen credentials about four and a half hours after the first data left the infected hosts. Between 16:20 and 17:01 UTC, AWS instance role credentials taken from compromised CI runners and Kubernetes nodes were checked from two IP addresses. Each check asked AWS who the credential belonged to and then listed the available Bedrock foundation models.
That pattern has a name: LLMjacking. The goal is to use someone else's cloud account to run expensive AI models, either for the attacker's own use or to resell access. In a few environments, the attacker also listed IAM roles, users and access keys, which points to an interest that goes beyond free model calls.
Wiz also notes that the payload shows strong signs of being written with the help of an AI model: very verbose variable names, generic error handling everywhere and code paths that fail silently on Windows. An AI generated stealer that targets AI tools to steal AI credentials is a fitting summary of where software supply chain attacks stand in 2026.
How the attacker got in
The most uncomfortable part of the story is the entry point. After the first compromise in March, LiteLLM rebuilt its release process. Releases moved to a private repository, artifacts were only published through GitHub's trusted publishing, Docker tags were made immutable and images were signed. The final publish step can only run from one account tied to one laptop in LiteLLM's office.
The attacker did not break those controls. They went around them with legitimate credentials. According to LiteLLM, the attacker held GitHub CLI tokens of three developers, one of them an organization owner. On the Monday before the attack, LiteLLM had temporarily widened release permissions so two engineers could publish daily bugfix backports. The owner token was enough to disable branch protection, and the second developer's token satisfied the approval gate.
LiteLLM believes the tokens came from its own internal LiteLLM deployment. The company found an unexpected, innocent looking user account in that deployment, which was reachable from the public internet. Its investigation also found that in specific situations, Claude Code can embed a user's GitHub CLI OAuth token into a response body. When response bodies are logged, as an AI gateway often does, those tokens can end up in the gateway's logs. LiteLLM suspects the attacker reached the internal deployment through a recently patched vulnerability, read the logs and collected the tokens. That part is not confirmed yet, and the company says it will keep updating its report.
Second time this year
This is not LiteLLM's first incident in 2026. On 24 March, versions 1.82.7 and 1.82.8 were published to PyPI with a credential stealer. That time, the entry point was a poisoned release of the Trivy security scanner that LiteLLM used in its CI pipeline, part of a larger campaign that Datadog and others link to a group called TeamPCP. The March packages were live for about 40 minutes.

The two attacks differ in an important way. In March the attacker bypassed the official pipeline and uploaded directly. In October the attacker used the official pipeline, so the artifacts were built, signed and published exactly like a real release. Signature checks and trusted publishing could not catch it, because from the system's point of view nothing was wrong. Datadog says no link between the two incidents has been established so far.
Who is affected and what to do
LiteLLM's guidance is clear. If an environment started Python with `litellm==1.107.0` installed, or a container ran the affected image digest, treat it as compromised. You can check the installed version with `pip show litellm` and search for `litellm-1.107.0.dist-info`, `cook.pth` and `sitecustomize.py`. Finding them confirms exposure, but not finding them proves nothing, because containers and temporary folders get cleaned up.
The steps LiteLLM recommends, based on advice from researcher LidorMachluf who helped detect the incident:
- Do not start by running `pip install`. Any Python start reruns the malware, including pip itself.
- From the shell, delete `cook.pth`, `cook.py`, `sitecustomize.py` and matching cached `.pyc` files from every affected `site-packages`.
- Stop the detached Python daemon that holds `/tmp/remote_code_loader.lock`.
- Reinstall pinned to `litellm==1.106.2`, or better, rebuild images and virtual environments from scratch.
- Rotate everything the host could reach: the instance or task IAM role, every provider key in the LiteLLM proxy database, the master and virtual keys, the database password and any secret in any process environment on that host.
- Check AWS CloudTrail for `GetCallerIdentity` calls from the instance role around install time, and for any later use of those credentials from outside your infrastructure.
Teams that did not install anything in the window should still pin LiteLLM to an explicit version and stop using moving tags like `latest` in production. LiteLLM itself also mentions an embargoed vulnerability fix for enterprise customers, with public disclosure scheduled for 27 October. Open source users should watch for that release.
Why it matters
LiteLLM sits in a uniquely sensitive spot. An AI gateway is designed to hold the keys to every model provider a company uses, and it often logs requests and responses for cost tracking and debugging. This incident shows that both properties can turn against its users. The gateway's database became a direct target, and the gateway's own logs were, according to LiteLLM, the place where the attacker found the tokens to break in.
There is a broader lesson for anyone using AI coding agents. Tools like Claude Code, Cursor and Codex work with real developer credentials on real machines. When those credentials can leak into model responses, and those responses land in logs, every log store becomes a secret store. That was a known risk in theory. Here it appears to have been part of a real attack chain against a major open source project.
Our take
LiteLLM did several things right after March, and the October attacker still got through. That is the honest takeaway. Signed artifacts and trusted publishing protect against outsiders uploading packages. They do not help much when an attacker holds an owner token and simply drives the real pipeline. Temporary permission changes, like the backport rights granted on Monday, are exactly the kind of small exception attackers wait for.
For teams building with AI, three habits would have limited the damage here: pin dependency versions and image digests instead of tags, keep provider keys out of hosts that do not strictly need them, and treat AI gateway logs as sensitive data with the same protection as a password vault. The speed of the response deserves credit, and so does the detailed public report. But a popular AI library being poisoned twice in seven months is a signal that the AI tool chain is now a main target, not a side door.
Sources: LiteLLM incident report, SafeDep, Wiz, Datadog Security Labs, Socket, OSV MAL-2026-2144, LiteLLM March 2026 report, Endor Labs on the March incident.
Source: docs.litellm.ai