LiteLLM's Poisoned 1.107.0 Release Stole Keys for Two Hours
By TechPulse USA Staff — 25 October 2026

Photo: File photo of server racks at the NERSC data centre. This is not a photograph of LiteLLM or its offices. Credit: NERSC, via Wikimedia Commons, CC0 public domain dedication.
Here is the nightmare version of a software update. You run one routine install, from the official registry, of a tool you already trust — and the update itself is the attacker. That is what happened to users of LiteLLM on Wednesday, 21 October 2026, when version 1.107.0 of the popular open-source AI gateway reached PyPI and Docker carrying a credential stealer and a remote-access backdoor.
The poisoned release did not last long. It did not need to. In roughly two hours on PyPI it was downloaded about 49,000 times, according to ClickPy data cited by Wiz Research. And because LiteLLM sits between applications and the AI providers they pay for, the machine it landed on was often exactly the machine holding the keys worth stealing.
LiteLLM, built by BerriAI, lets developers call more than 100 model providers through a single interface. Many teams also run it as a proxy: one gateway that holds the company's OpenAI, Anthropic, Azure and Bedrock keys. That central role is what turned an ordinary supply-chain incident into a scramble. If the gateway is compromised, the attacker does not have to hunt for keys one by one. They are already gathered in one place.
We checked TechPulse USA's own archive before writing this: we have not covered LiteLLM before, and the closest earlier stories in our supply-chain file are different incidents entirely. This one stands on its own, and it deserves to be read as a warning, not a footnote.
Two hours on PyPI, longer on Docker
The timeline, as published by LiteLLM itself, is uncomfortably precise. At 11:39:51 UTC on 21 October, seven malicious wheels of litellm 1.107.0 were uploaded to PyPI. The last of them landed at 11:40:13 UTC. PyPI had removed the release by 13:23 UTC.
Docker users had a longer window to worry about. Compromised images appeared at 11:46:56 UTC under four tags: v1.107.0, latest, main-latest and main-stable. The affected GitHub Container Registry tags were unavailable by 13:51 UTC, and Docker Hub tags were removed or repointed to clean images by 14:20 UTC.
That floating-tag detail matters more than it looks. Anyone who pulled latest on the morning of 21 October may have received the poisoned build without ever typing 1.107.0. LiteLLM's advice is blunt: if you ran an unpinned install or one of those tags in the window, assume compromise. The most recent safe version is 1.106.2.
Enterprise customers pulling from LiteLLM's private registry were not affected, LiteLLM said. Everyone else on the public registries that morning needs to check, not guess.
What the poisoned build actually did
The payload was small, nasty and — this is the part that should alarm every Python shop — automatic. Installing the package dropped three files into Python's site-packages directory: cook.pth, cook.py and sitecustomize.py. Python runs .pth files and sitecustomize.py at interpreter startup, so the malware fired every time Python started, even if no program ever imported LiteLLM.
The first file, cook.pth, simply imports cook. That loads cook.py, a stealer Wiz calls privcollect, built from 16 modules. It harvested browser credentials and cookies from Chrome, Firefox, Edge and Safari; AWS credentials from config files, environment variables and instance metadata; Google Cloud service-account keys; Azure tokens from the CLI cache; SSH private keys; GPG keys; shell history; and API keys for OpenAI, Anthropic, Cohere and other providers. Where a LiteLLM proxy database was configured, it queried the proxy's own credential table directly for every stored provider key.
The stolen data was encrypted and sent by HTTP POST to an attacker-controlled lookalike domain, www.litellm.dev, at its healthcheck endpoint. The real project lives at litellm.ai. One letter of difference in the domain, one hyphen of difference in a repository name — that was the whole disguise, and it worked.
The second component, sitecustomize.py, ran only on Linux and macOS. It forked a background daemon, took a lock file so only one copy ran, and then checked a GitHub file every hour for a domain to fetch new code from. Aikido researcher Ilyas Makari described it plainly: "It forks a background daemon that acquires a lock at '/tmp/remote_code_loader.lock' to prevent multiple instances, then enters an infinite loop." Every hour, he said, the daemon fetched the attacker's current command-and-control domain from a GitHub repository, "then fetches and executes a Python payload from http://{domain}/codepy."
The good news, such as it is: that GitHub dead-drop file was never populated beyond initial test values, according to Wiz, and GitHub took the repository down. No second-stage payload was observed in the wild. The bad news: the stealer did not need a second stage. It had already done its job.
Wiz researchers Benjamin Read and Rami McCarthy put the novelty of the design in one sentence: "The dual-technique approach, using both .pth files and sitecustomize.py simultaneously, appears to be the first documented case in the wild." In other words, the attacker did not pick one persistence trick. They used two, in parallel, so that killing one would not necessarily kill the infection.
How a hyphen and three tokens opened the pipeline
This was not a typosquatted package. Nobody was tricked into installing litellm-official or some misspelling. The poisoned wheels came through LiteLLM's own release pipeline, with what looked like legitimate build provenance, because the attacker had taken over the pipeline itself.
LiteLLM's account, published while its investigation was still running, reads like a post-mortem written on no sleep — and like a checklist of controls that each failed in turn. The project had hardened its pipeline after a March 2026 compromise, moving releases to a private repository, using trusted publishers and signing Docker images. Then, on Monday 19 October, it temporarily widened release permissions so two internal engineers could publish daily bugfix backports.
The attacker, LiteLLM says, held GitHub CLI OAuth tokens belonging to three engineers. One account overrode branch protection on the release workflow and force-pushed a change. A second account satisfied the production approval gate. A third deleted the workflow records. The modified workflow pointed the releaser at Berri-AI/litellm — a hyphenated lookalike of the real BerriAI/litellm repository — and the pipeline faithfully built, signed and published the poisoned artifacts.
How did the attacker get those tokens? LiteLLM believes they were lifted from the logs of an internal LiteLLM deployment that was exposed to the public internet. The company says it observed cases in which Claude Code embeds a user's GitHub CLI OAuth token in a response body, and that such bodies, when logged, can leave tokens sitting in logs. It is careful about the limits of that theory, and so are we: LiteLLM says it has not yet confirmed how the attacker got into its internal deployment, and currently suspects a recently patched vulnerability. That is a belief, not a proven entry route, and it should be read as one.
There is a second, older LiteLLM compromise in the background, and it is worth naming so the two are not confused. In March 2026, versions 1.82.7 and 1.82.8 were compromised in an incident Datadog Security Research linked to TeamPCP activity. Datadog says no connection between the March and October compromises has been established. Same package, same class of trick, different incident — and, for now, no evidence of the same actor.
The stolen keys were used within hours
This is the part that kills any hope of a quiet cleanup. Wiz observed abuse of the stolen credentials starting about four and a half hours after exfiltration. Between 16:20 and 17:01 UTC on 21 October, the attacker validated AWS instance-role credentials harvested from compromised continuous-integration runners and Kubernetes nodes, from two IP addresses, then called Amazon Bedrock's model-listing APIs.
That sequence — check who the credential belongs to, list the models it can call — is the signature of LLMjacking: using someone else's cloud account to run AI models on their bill. In a small number of environments, Wiz said, the attacker also enumerated IAM roles, users and access keys, and performed general discovery across accounts and audit trails.
Four and a half hours. That is the gap between a developer running a routine install on a Wednesday morning and an attacker testing the stolen keys against a cloud AI service the same afternoon. It is also why every remediation guide for this incident says the same thing in different words: do not wait for evidence that your keys were used. Assume it.
The pattern should feel familiar to regular TechPulse USA readers, and not in a good way. We covered a critical PHP flaw hiding in plain sight days earlier, and a Brotli flaw that could own a Node.js server — both cases where the dangerous thing was not an exotic exploit but a trusted component doing something nobody expected. LiteLLM is the supply-chain version of the same lesson: the blast radius of a trusted tool is every machine that trusts it.
If you installed 1.107.0, do this now
First, the counterintuitive part: do not start by reinstalling. LiteLLM warns that any Python start in the affected environment runs the payload again, and that includes running pip. Delete cook.pth, cook.py and sitecustomize.py — plus any matching cached copies — from every affected site-packages directory, from the shell, before you touch pip at all.
Next, kill the detached Python daemon holding the remote-code-loader lock file. Then rebuild the environment or image from scratch if you can; that is better than cleaning in place. If you must reinstall in place, pin litellm to 1.106.2.
Then comes the part nobody enjoys: rotate everything the host could reach, from a clean machine. That means the cloud instance or task role, every provider key stored in the LiteLLM proxy database plus the master and virtual keys, the database password, and any secret that sat in the environment of any process on the host. Check your cloud audit trail for identity checks from the instance role around install time, then for use of that role's credentials from outside your own infrastructure.
And here is the sentence that should be printed on the wall of every platform team: uninstalling LiteLLM does not remove these files. They live in site-packages, not in the package directory, so pip uninstall leaves them behind. If you only uninstalled and moved on, you are not clean. Check for the files, check for the marker file the stealer leaves behind, and check for the daemon's lock file. Finding one confirms exposure. Not finding one, LiteLLM warns, proves nothing — containers and temporary-file cleanup can erase the markers while the stolen keys stay stolen.
Why signed builds did not save anyone
The most uncomfortable question in this incident is not how the attacker got in. It is why the defences that were supposed to catch a bad build did not. LiteLLM had moved releases to a private repository, made Docker tags immutable, and signed its images. All of that was real, and none of it helped, because the attacker did not forge a signature or sneak a file past a check. They used stolen owner-level access to change the release workflow itself, and the pipeline then did exactly what it was told: build from the wrong repository, sign the result, and publish it.
Signing proves that a particular pipeline run produced a particular artifact. It does not prove that the pipeline's instructions were the ones anyone reviewed. That distinction is the whole story here, and it is why the fix cannot just be "sign more things." Release workflows need to be locked to approved repositories, release identities need to be separate from developer identities, and a change to the release path itself needs to be the hardest change in the system to make — not something a single token can force through.
JFrog security researcher Guy Korolevski put the downstream risk bluntly: "A single compromised install can hand an attacker the ability to push malicious code downstream." One gateway, one install, one afternoon — and the attacker is standing inside the build systems of everyone downstream.
Our verdict: pin everything, trust nothing by tag
Let us be direct, because the hedged version of this advice is what gets people hurt. If you run AI infrastructure, stop installing latest. Stop installing unpinned. Pin exact versions, verify hashes or digests before deployment, and block mutable tags in production. Treat developer CLI tokens as the high-value secrets they are — because in this incident, three of them were enough to ship malware to 49,000 downloads under the project's own name.
LiteLLM did several things right after the fact: it published a detailed timeline, named the affected artifacts precisely, and told users to assume compromise rather than wait for proof. That candour matters. But candour after the fact is not a control. The control that would have stopped this was boring, unglamorous and available all along: a release pipeline that cannot be repointed at a lookalike repository by a stolen token, no matter how senior the account it came from.
Until that becomes standard, every AI gateway, every proxy, every package that holds your provider keys should be treated as a vault door. LiteLLM 1.107.0 was a reminder that the door can be opened from the inside — by the very pipeline built to keep it shut. The teams that survive the next one will be the ones who checked their pins, checked their site-packages, and rotated their keys before they had proof they needed to. The rest will be reading timelines like this one, wondering how two hours became the most expensive install of their year.
For context on how supply-chain attacks keep reaching developers through trusted channels, see our earlier report on GhostAction hijacking GitHub accounts to steal secrets.
Frequently asked questions
Am I affected if I only pulled the latest Docker tag?
Possibly, yes. The tags v1.107.0, latest, main-latest and main-stable all served the compromised image for part of 21 October. LiteLLM says anyone who used those tags between 11:46 and 14:20 UTC should assume compromise and check image digests, not just tag names.
Does uninstalling LiteLLM remove the malware?
No. The three dropped files live in Python's site-packages directory and survive a package uninstall. They must be deleted manually, the background daemon killed, and the environment rebuilt or reinstalled pinned to 1.106.2.
What is the safe version to use now?
LiteLLM and Wiz both name 1.106.2 as the most recent safe version. Release candidates 1.107.0rc1 and 1.107.0rc2 were also reported clean, but pinning the known-safe 1.106.2 is the advice LiteLLM itself gives.
Was my data stolen even if the backdoor never ran a second stage?
The stealer and the backdoor are different components. The GitHub dead-drop file for the backdoor was never populated beyond test values, so no second-stage code was observed. But the stealer ran at Python startup and exfiltrated credentials independently — so a dormant backdoor does not mean your keys are safe.
Is finding sitecustomize.py proof I was hit?
No — Debian and Ubuntu ship a legitimate sitecustomize.py for the system Python. Match on hash or content, not filename alone. Finding cook.pth is confirmation; a sitecustomize.py hit on its own is not.
Can I just run pip show to check?
No — any Python start in a suspect environment, pip included, re-triggers the .pth and sitecustomize hooks. Check from the shell outside the suspect interpreter: build logs, lockfiles, deployment records and the original image digest, not a live pip query.
What is LiteLLM doing next?
Tokens abused in the attack have been revoked and maintainer permissions cut to a minimum, per SOCRadar's summary of the maintainer response. SOCRadar also reports a separate LiteLLM vulnerability scheduled for public disclosure on 27 October, already fixed in an embargoed enterprise release — single-source, attributed as such; do not present it as confirmed by LiteLLM itself.
Update, Oct. 25: the indicators to hunt for
Update, Oct. 25: if you are still hunting for traces of the 21 October install, the cleanup guides agree on four indicators this post did not name. First, the stealer's marker file: /tmp/.pc_once_72129118c59f5636c0bb — written only after a successful upload, so finding it confirms your secrets left, while not finding it proves nothing, because container and temporary-file cleanup erase it. Second, the affected container image digest: sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e — any container that ran that digest should be treated as compromised, whatever tag it was pulled under. Third, the network hunt: egress or proxy logs for POSTs to www.litellm.dev/healthcheck, and CloudTrail for sts:GetCallerIdentity calls from the instance role followed by bedrock:ListFoundationModels — Wiz attributes the Bedrock probes to 168.100.8.57 and 165.227.201.8. Fourth, the hash check for sitecustomize.py: match the file's SHA-256 against the published IOC lists rather than trusting the filename, since a legitimate sitecustomize.py ships with some system Pythons. None of this changes the post's core advice — delete the three files from the shell, kill the daemon, rebuild pinned to 1.106.2, rotate everything from a clean machine — but it turns 'check for the files' into a check you can actually run.
Related reading: the PHP flaw hiding in plain sight and the Brotli flaw that could own a Node.js server.
Sources: LiteLLM's security incident post (BerriAI, 21 October 2026, updated 23 October); Wiz Research, "LiteLLM Compromised, Steals Credentials"; SecurityWeek, "LiteLLM Compromised in Fresh Supply Chain Attack" (23 October 2026); Datadog Security Labs, "LiteLLM supply chain compromise: What you need to know"; Aikido Security, "LiteLLM compromised: infostealer and RAT in PyPI 1.107.0"; The Hacker News, "LiteLLM Suspects GitHub Token Leak in AI Gateway Logs Behind Malicious Package Release" (quotes from Wiz researchers Benjamin Read and Rami McCarthy, and Aikido researcher Ilyas Makari).
TechPulse USA covers global technology and AI news for readers in the United States, Europe, Canada and Australia, with every fact checked against primary sources before publication. If you spot an error in this story, tell us and we will correct it.
Comments
Post a Comment