The package that routes your model keys became the package that steals them.
On 21 October 2026, LiteLLM's release pipeline shipped version 1.107.0 to PyPI and official Docker registries with a credential stealer and a remote-code loader baked into the install. The official Git tag stayed clean. The wheels and images did not. For teams that treat LLM gateways as boring plumbing, the incident is a receipt: the gateway is now a first-class supply-chain target, and agent tooling can leak the credentials that sign the next release.
LiteLLM's second 2026 supply-chain break lands on the gateway everyone pins loosely
LiteLLM sits in front of provider APIs for a large share of Python agent and proxy stacks. Datadog Security Labs puts weekly downloads near 23 million. That reach is why a short window on PyPI still matters: continuous integration that floats litellm without a pin will pull whatever is current.
This is the second documented compromise of the package in 2026. Earlier wheels 1.82.7 and 1.82.8 carried a similar .pth startup pattern. LiteLLM's 21 October post does not claim a link between the two campaigns. Check Point Research's mid-October CVE writeup on LiteLLM proxy bugs is separate context: the gateway was already on researchers' desks before the poisoned release.
Malicious wheels, mutable Docker tags, and a lookalike Berri-AI publish path
LiteLLM's incident post, last updated 21 October 2026 at 20:30 UTC, states that all seven litellm==1.107.0 wheels were live on PyPI from 11:39:51 to 13:23 UTC.
Docker Hub tags v1.107.0, latest, main-latest, and main-stable pointed at compromised image index sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e from 11:46:56 to 14:20 UTC. Matching GHCR tags for litellm, litellm-database, and litellm-non_root were compromised from 11:46 UTC until made unavailable by 13:51 UTC. Enterprise customers on LiteLLM's private registry were not affected, the company says.
JFrog and OSV analyses describe three extra files under site-packages: cook.pth (imports cook), cook.py (AES/RSA-encrypted exfil of browser, cloud, CI, and AI-tool secrets to a lookalike healthcheck endpoint), and sitecustomize.py (hourly remote-code fetch). Because Python runs .pth files and sitecustomize.py at interpreter start, the payload fires even when no application imports litellm. The official v1.107.0 source tag on GitHub lacks those files. LiteLLM says the compromised artifacts were built from attacker-controlled Berri-AI/litellm rather than BerriAI/litellm.
Org-owner force-push turned Trusted Publishers at a hyphenated lookalike
After hardening that followed the March incident (private release repo, Trusted Publishers, immutable Docker tags, signing), LiteLLM says Monday's temporary expansion of release permissions for bugfix backports coincided with attacker possession of three developer GitHub CLI credential sets. One token could run workflows. Branch protection blocked an unauthorised workflow change at 10:08:29 UTC; seconds later, a privileged credential overrode protections. Staging and production then built from the lookalike repo. A second developer credential cleared the production approval gate. A third deleted workflow records after publish. By 13:23 UTC PyPI had removed 1.107.0; Docker Hub tags were cleaned or repointed by 14:20 UTC.
The credential path LiteLLM currently believes: Claude Code embedded GitHub CLI OAuth tokens in response bodies; those bodies were logged on an internal LiteLLM deployment exposed to the public internet; an unexpected user account on that deployment is under investigation. How the attacker first reached that deployment remains unsettled on the post, with a recently patched vulnerability named as a working suspicion.
Pin the wheel, rebuild the image, rotate every secret the host could reach
Operators who installed 1.107.0 or pulled the listed Docker tags in the windows above should treat the environment as compromised. LiteLLM's remediation, drawing on community detection help, starts outside Python: delete cook.pth, cook.py, sitecustomize.py, and matching __pycache__ artifacts from every site-packages tree; kill the daemon holding /tmp/remote_code_loader.lock; then rebuild from litellm==1.106.2 or an earlier explicit pin. Do not open with pip install on a dirty interpreter, because that start re-runs the stealer.
Rotate instance IAM roles, every provider key and master or virtual key in the LiteLLM proxy database, DATABASE_URL passwords, and any secret present in the process environment. Check cloud audit logs for GetCallerIdentity from the instance role around install time, then for use of those credentials from outside your network. Prefer fresh virtualenvs and images over in-place cleanup.
A two-hour window still leaves exposure estimates thin
LiteLLM has pulled the artifacts and published a detailed timeline. Independent labs confirm the wheel payload shape. What remains thinner: a public count of installs during the window, confirmation of second-stage C2 beyond the observed test domain list, and a closed attribution to a named actor. Absence of the /tmp/.pc_once_* marker does not prove a clean host, LiteLLM notes, because containers and temp cleanup erase it.
How the internal deployment was first opened stays under investigation
LiteLLM says the incident is contained and the investigation continues. Outstanding for readers: the exact entry that created the unexpected internal user, whether Claude Code's OAuth-in-response behaviour has a durable product fix beyond log hygiene, and how Trusted Publisher bindings will be re-locked after the temporary permission expansion. Until those answers land, pin releases, treat mutable latest tags as hostile by default, and keep agent response bodies that may contain OAuth material out of publicly reachable log stores.
