Safety & Risk 2026-10-22

LiteLLM 1.107.0 Shipped a Credential Stealer to PyPI and Docker for About Two Hours -- and LiteLLM Believes the Stolen GitHub Tokens Came From Its Own Proxy's Logs

The popular open-source LLM gateway published a poisoned release built from a lookalike repository. The payload ran on every Python start, went after provider keys stored in the proxy database, and stolen AWS credentials were checked for Bedrock access within hours. LiteLLM's account of how the attacker got in is still provisional.

On October 21, 2026, a malicious litellm==1.107.0 reached PyPI and Docker. In LiteLLM's own incident post, the PyPI wheels were "live from 11:39:51 to 13:23 UTC", and the Docker Hub tags v1.107.0, latest, main-latest and main-stable pointed at a compromised image "from 11:46:56 to 14:20 UTC" (GHCR until 13:51). Version 1.106.2 is the safe pin. Customers on the private enterprise registry were not affected.

What the release did

SafeDep's analysis found that every wheel installed three files into site-packages: cook.pth, cook.py and sitecustomize.py. Both mechanisms run "when any Python process starts on the host, even one that never imports litellm". The only visible change in the source distribution was one line, data = "cook", in the maturin build section, and no public commit in BerriAI/litellm contains it. Wiz describes the stealer, internally named privcollect, as 16 modules covering browser credentials, AWS, GCP and Azure secrets, SSH and GPG keys, and LLM provider keys. It also queried the proxy's own database with SELECT * FROM "LiteLLM_CredentialsTable" LIMIT 500. The second file polled a GitHub dead drop, domain.txt, for a command server, though Wiz says domain.txt "was never populated beyond initial test values".

How it happened, per LiteLLM

After a March incident, LiteLLM had moved releases to a private repository with Trusted Publishers and a physically controlled publishing account. On Monday it "temporarily expanded release permissions" for daily backports. The attacker held three developers' GitHub CLI credentials, one belonging to an organisation owner, used it "to disable branch protections and force push", and ran the workflow against a lookalike repository, Berri-AI/litellm. On the source of those tokens, LiteLLM writes that "we have observed specific situations in which Claude Code will embed a user's GitHub CLI OAuth token into a response body," that such bodies could land in LiteLLM logs, and that an internet-exposed internal deployment held "an unexpected, innocuously named user account". It says it is "still working on confirming" this account. Claude Code's October 21 release notes do not mention it.

What happened next

Wiz observed stolen AWS instance-role credentials being checked "approximately 4.5 hours post-exfiltration", each with sts:GetCallerIdentity, then bedrock:ListFoundationModels, "consistent with LLMjacking". Downstream, Google's ADK committed a cap on LiteLLM below 1.106.3 because its extensions extra "accepted any litellm release from 1.84 up". Separately, the hosting platform Railway disclosed the same day that an unauthorised party may have read decrypted customer environment variables, which it believes is "part of a series of attacks recently targeting platform companies with the aim of compromising AI inference providers". Railway did not link its incident to LiteLLM, and neither do we.

What remains uncertain. The token-exposure path and the initial access route are LiteLLM's working hypotheses. LiteLLM says an embargoed fix for its enterprise registry is scheduled for disclosure on October 27.

Analysis: An LLM gateway is a key vault by design, so its logs and its release path need vault-grade controls. Log redaction must treat any tool output as possibly holding tokens, and a temporary widening of release rights deserves the same review as a code change. Any team that installed 1.107.0 should follow LiteLLM's order of operations: delete the planted files from a shell before running Python again, then rotate every provider key stored in the proxy database.

A poisoned LiteLLM 1.107.0, built from a lookalike repository, was on PyPI from 11:39 to 13:23 UTC on October 21 and in Docker tags until 14:20, installing a stealer that ran on every Python start and harvested cloud, SSH and LLM provider keys; Wiz saw stolen AWS credentials probed for Bedrock within hours, and LiteLLM provisionally traces the attack to GitHub CLI tokens found in its own internet-exposed deployment's logs.