LiteLLM Supply-Chain Attack: Protect Your Python & AI Stack

Stacked shipping containers at a port, a metaphor for the software supply chain

Last week one of the most popular Python libraries in the AI world shipped malware to its own users. On 21 October 2026, a poisoned release of LiteLLM, the open-source gateway many teams use to talk to OpenAI, Anthropic, Gemini and other model providers, was published to PyPI and to the project's official Docker images. For about two hours, anyone who installed or pulled the "latest" version received a credential stealer instead of a routine update.

No code was broken into. The attackers used stolen developer credentials to run the project's real release pipeline against a lookalike repository. If you write Python, run AI apps, or manage CI/CD, this incident is a clear lesson in how modern supply-chain attacks work and what actually stops them. This post covers what happened, how to check whether you were affected, and the habits that would have protected you.

What happened in the LiteLLM 1.107.0 compromise

According to LiteLLM's own incident report, the malicious litellm==1.107.0 package was live on PyPI from roughly 11:39 to 13:23 UTC (about 5:09 PM to 6:53 PM IST) on 21 October. The Docker tags v1.107.0, latest, main-latest and main-stable pointed to compromised images from 11:46 UTC until they were cleaned up by 14:20 UTC. Earlier versions, including 1.106.2, are safe, and the official source tag on GitHub never contained the malicious files.

The project had already hardened its release process after an earlier incident in March 2026. It used a private release repository, trusted publishing, immutable Docker tags and signed images. The attacker got around all of it with stolen GitHub CLI OAuth tokens belonging to three engineers. One token belonged to an organisation owner and was used to override branch protection. A second satisfied the production approval gate. A third deleted the workflow logs afterwards. The release workflow was quietly pointed at Berri-AI/litellm, a fork whose name differs from the real BerriAI/litellm by a single hyphen.

The result was the worst kind of supply-chain attack: a malicious package published through the official channel, with build provenance that looked legitimate on the surface. As Datadog Security Labs points out, the provenance faithfully recorded the malicious fork as the source. The signature was valid. It simply described the wrong repository.

Why this payload was so dangerous

Most people assume a bad library only hurts you when you import it. This one did not wait. The wheels dropped three extra files, cook.pth, cook.py and sitecustomize.py, into the root of site-packages. Python processes .pth files and sitecustomize automatically every time the interpreter starts, so any Python process in that environment ran the malware, even a plain pip install of something unrelated.

Microsoft's analysis and the OSV malicious-package entry describe a collector that went after nearly every secret a developer machine holds: cloud credentials (including instance metadata), SSH, GPG and TLS keys, Git, npm and PyPI tokens, .env files, Kubernetes and Vault secrets, browser passwords and cookies, and sessions for AI coding tools. On LiteLLM proxy hosts it also tried to read the stored provider API keys from the database. The data was encrypted and sent to a lookalike domain. A second, Unix-only component could fetch and run more code later.

Because LiteLLM usually sits between apps and paid model providers, one infected gateway could leak every API key a company uses for AI.

Were you affected? How to check safely

You should treat an environment as compromised if any of the following is true:

  • You installed an unpinned LiteLLM (for example pip install litellm or a loose litellm>= requirement) during the PyPI window on 21 October.
  • A container ran the Docker or GHCR tags v1.107.0, latest, main-latest or main-stable during the image window.
  • A lock file, internal mirror, pip or uv cache, or built image contains litellm 1.107.0.

The most important point: do not run Python or pip inside a suspect environment to check. Because the payload fires at interpreter start, even pip show litellm can re-trigger it. Inspect the files from the shell or, better, from a known-clean machine. Look for litellm-1.107.0.dist-info, cook.pth, cook.py and sitecustomize.py at the top of site-packages. Finding them confirms exposure. Not finding them does not prove you are clean, because containers and temp-folder cleanup can erase traces.

If you were affected

  • Isolate the machine, container or CI runner and stop any running Python processes.
  • Rebuild virtual environments and images from scratch and pin to a known-good version such as 1.106.2. Deleting only the litellm folder leaves the startup files behind.
  • From a clean machine, rotate everything the host could reach: cloud and workload roles, LLM provider keys, the LiteLLM master and virtual keys, the DATABASE_URL password, Git and registry tokens, SSH keys and AI tool sessions.
  • Revoke active sessions as well as rotating passwords, since existing tokens may keep working.
  • Review cloud audit logs (for example AWS CloudTrail) for credential use from outside your network after the install time.

The bigger lesson: trust is now the attack surface

This was not a typo-squat that a careful developer would have avoided. The package had the right name, came from the right registry and was signed by the right pipeline. That is what makes 2026's supply-chain attacks hard: attackers go after the people and tokens behind trusted projects, then let normal automation deliver the payload. The same month also brought the PHP2Shell emergency, a reminder that your foundations matter as much as your own code.

Two weak points stand out. First, floating versions and mutable tags. If your build pulls "latest" from PyPI or Docker Hub, you install whatever the registry serves at that moment, good or bad. Second, long-lived developer tokens. LiteLLM's investigation found GitHub CLI tokens ending up in application logs on an internet-exposed internal deployment, which is how the attacker probably obtained them. Logs, AI tool transcripts and debug output are now places where secrets leak.

Practical checklist: harden your Python and AI supply chain

None of these steps are exotic. Together they turn a two-hour malicious release into a non-event.

  • Pin exact versions in lock files. Use pip-tools, uv lock or Poetry so every build installs the same versions until you deliberately upgrade.
  • Enforce hash checking. pip's secure installs guide explains --require-hashes, which refuses any file whose hash is not already in your requirements. A newly published malicious release cannot sneak in.
  • Add a release cooldown. Do not adopt a new version on the day it ships. A delay of a few days lets the community and scanners catch poisoned releases first. This incident lasted two hours.
  • Pull images by digest, not tag. Reference image@sha256:... in deployments. Tags like latest can be repointed. Digests cannot.
  • Check provenance carefully. Signatures and attestations help, but read what they say. Confirm that the source repository is exactly the one you expect.
  • Use an internal mirror with review. Admit new package versions to your proxy only after automated scanning against feeds such as OSV.
  • Restrict outbound traffic. Build agents, AI gateways and containers rarely need unrestricted internet access. Egress allowlists stop most exfiltration.
  • Shorten token lifetimes. Prefer short-lived OIDC credentials in CI, require phishing-resistant MFA for organisation owners, and review who can bypass branch protection.
  • Keep secrets out of logs. Scrub request and response bodies, especially from AI coding tools and LLM gateways, and scan logs for tokens.
  • Separate developer machines from production secrets. A laptop that runs experimental packages should not hold long-lived production cloud keys.

For QA and DevOps teams

Supply-chain checks fit naturally into a test pipeline. Add a job that fails the build if any dependency is unpinned or missing a hash, if a Docker reference uses a tag instead of a digest, or if a package matches a known malicious advisory. Treat dependency upgrades as changes that need review, not as background noise from a bot. If you followed our security testing guide for QA engineers, add this to your regression suite.

FAQ

Is it safe to use LiteLLM now?

Yes, as long as you install a verified clean version. The malicious 1.107.0 artifacts were removed from PyPI, Docker Hub and GHCR. Pin an explicit version, check hashes and follow the project's advisories for later releases.

I never imported LiteLLM. Could I still be affected?

Yes. If version 1.107.0 was installed in an environment, starting any Python process there could run the payload. That includes tools that only list LiteLLM as an indirect dependency.

Does uninstalling the package fix it?

No. The startup files sat outside the litellm folder, and stolen credentials stay stolen. Rebuild the environment and rotate every secret the host could reach.

Would antivirus have caught this?

Detections arrived within a day or so, and Microsoft Defender now flags the known files. Signature-based tools always lag behind a brand-new release, though. Pinning, hash checks, cooldowns and egress controls protect you from the next one before anyone has written a signature.

Does this only affect AI projects?

No. LiteLLM is an AI library, but the technique of hijacking a trusted release pipeline and abusing Python startup hooks works against any package on any registry. AI gateways are attractive targets because they hold so many valuable API keys.

Sources and further reading

Photo: Igor Ovsyannykov on Wikimedia Commons (CC0, via Unsplash)

Comments

Popular posts from this blog

When an AI Pentest Agent Hits Bank Portals — What QA Should Test Next

AI Phishing & Deepfake Scams: How to Spot Them (2026)