Poisoned LiteLLM 1.107.0 on PyPI Targets AI API Keys

LiteLLM, the large-model gateway tool, was hit by a supply-chain poisoning attack on October 21. Cloud security firm Wiz disclosed that the tampered LiteLLM 1.107.0 went live on PyPI that day, and that images on GHCR and Docker Hub tagged v1.107.0, latest, main-latest and main-stable were also implanted with the same stealer. The most recent safe version named by the maintainers is v1.106.2.

LiteLLM is developed by BerriAI. A common setup is to run it as an internal proxy that forwards requests through a single interface to hundreds of model services, including OpenAI, Anthropic and Bedrock. Behind that proxy sit the API keys for each vendor, and that is exactly what this attack went after.

It starts stealing as soon as it is installed

The malicious package drops three files in the root of site-packages: cook.pth, cook.py and sitecustomize.py. The first two rely on Python's .pth mechanism and run whenever the interpreter starts, so no application code needs to import LiteLLM.

The stealer, called privcollect internally, has 16 modules. Its targets include:

  • Browser credentials and cookies from Chrome, Firefox, Edge and Safari
  • Cloud credentials for AWS, GCP and Azure
  • API keys from AI vendors such as OpenAI, Anthropic and Cohere
  • SSH and GPG private keys, plus shell history
  • Upstream vendor credentials queried directly from the LiteLLM Proxy PostgreSQL database

The data is first encrypted with AES-256-CBC, with the key wrapped in RSA-4096, and then sent by HTTP POST to www.litellm[.]dev, a lookalike domain registered by the attacker. sitecustomize.py runs only on Linux and macOS and fetches a second-stage address from a “dead drop” repository on GitHub. Wiz says that file was never filled in beyond test values, and GitHub has since deleted the repository.

Laying out the timeline

Using the UTC times Wiz published, here are the rough windows for each stage:

StageTime (UTC)Duration
Lookalike repository receives 10 commits08:56–10:46About 1 hr 50 min
Malicious version live on PyPI11:39–13:20About 1 hr 41 min
Tampered Docker tags liveTaken down around 13:53About 2 hr 14 min from the PyPI upload
Attacker validates AWS credentials16:20–17:01About 4.5 hours after exfiltration

The hour or so on PyPI may not look long, but tags such as latest are pulled automatically by large numbers of CI pipelines and Kubernetes deployments, so exposure depends mostly on how many environments rebuilt their images in that window. Wiz has not given download figures, and the number of affected organizations cannot currently be verified.

After obtaining credentials, the attacker used AWS instance roles on compromised CI runners and Kubernetes nodes to call APIs including sts:GetCallerIdentity and bedrock:ListFoundationModels. Wiz says this matches the LLMjacking playbook, in which someone hijacks another party's cloud account to run large-model calls for free; in some environments the attacker also enumerated IAM as routine reconnaissance.

The entry point may be GitHub tokens

The 10 commits the attacker pushed landed in a lookalike repository, Berri-AI/litellm. The first nine carried GitHub signatures; the last was unsigned and used a different email address. BerriAI's account of events:

"malicious actions were taken through three engineers' GitHub accounts"

LiteLLM suspects the GitHub CLI OAuth tokens involved leaked from an internal deployment exposed to the public internet, possibly linked to a recently patched vulnerability; Wiz states explicitly that this is unconfirmed. BerriAI says all the tokens in question have been revoked. Teams that used 1.107.0, or pulled the images above during that window, need to rotate every cloud credential, model key and SSH private key readable on those machines.

Sources: Wiz research blog, CocoLoop, Wiz Threat Intelligence Center advisory, BerriAI public statement; we checked the affected versions and image tags, the malicious file names and the UTC time for each stage.