LiteLLM 1.107.0: a leaked key, a hijacked release pipeline, and a stealer that ran every time Python started
TechScripts Nepal · Kathmandu · October 26, 2026 · 6 min read
On October 21, 2026, a poisoned build of LiteLLM, a widely used Python library and proxy that lets applications talk to many AI model providers through one interface, was published to PyPI and Docker Hub. The malicious release was live for roughly two hours on PyPI and a little longer on Docker. LiteLLM has since published its own account of what happened, and it's worth reading closely, because the way the attacker got in is more instructive than the malware itself.
What shipped
The bad release was litellm==1.107.0. All seven of its wheels (PyPI's installable packages) were malicious, and the official Docker images for the same version carried the same payload. Security researchers who analyzed it describe a credential stealer and a remote code loader. The source code tagged in LiteLLM's GitHub repository did not contain the malicious files, because the artifacts were built from a different, attacker-controlled repository.
Exposure windows, all UTC and per LiteLLM's notice:
- PyPI: about 11:39 to 13:23.
- Docker Hub: about 11:46 to 14:20.
- GitHub Container Registry: from 11:46 until the tags were made unavailable by around 13:51.
LiteLLM says enterprise customers running its private enterprise release were not affected.
Why it ran even if you never imported it
The malware used a .pth file. Python reads these files in its site-packages folder every time the interpreter starts, and they can contain code that runs immediately. That means the stealer executed whenever Python launched in an affected environment, whether or not any of your code ever imported LiteLLM. Researchers also describe a sitecustomize.py hook and a detached background process.
This is the same lesson as the MALFEX npm campaign: "I never ran that package" is not a safe assumption once something has been installed.
How the attacker got in
LiteLLM's post-mortem lays the chain out step by step. It started months earlier.
- May 27: A configuration file containing the master key for a LiteLLM Agent Platform deployment was committed to a public GitHub repository. The commit was later force-pushed over, which removes it from the visible history, but the key was never revoked. A force-push hides a secret; it doesn't cancel it.
- October 10: The attacker used that still-valid key to make authenticated API calls, and one call returned the GitHub CLI OAuth token belonging to an organization owner.
- October 10 and 12: Workflows running on temporary branches sent CI secrets, including maintainers' tokens, to an external webhook, and the workflow runs were deleted within minutes.
- October 21: Using the owner's token, which could override branch protection, the attacker altered the release workflow so it would build from a lookalike fork, ran a staging build, then triggered production. A second maintainer's stolen token approved the production gate.
- 11:39 UTC: The seven wheels were published. Run records were deleted afterwards and the main branch was force-pushed back to hide the change.
LiteLLM notes it had hardened its release process after an earlier incident in March, with private repositories, trusted publishing, immutable Docker tags, and signed images. The attacker went around those controls using stolen, legitimate credentials from people who had the authority to approve releases.
A candid detail: LiteLLM's first report suggested the tokens had been taken from an internal deployment's logs, and the company later said that was wrong after reviewing the request logs. Early incident accounts are often incomplete, so check LiteLLM's canonical post for the current version.
Are you affected?
You should treat an environment as compromised if:
- an unpinned
litellmwas installed or upgraded during the PyPI window, - Python ran with
litellm==1.107.0(check withpip show litellm), or - a container ran an affected image pulled during the Docker or GHCR windows.
LiteLLM warns that not finding indicators doesn't prove a system is clean. Known indicators include files named cook.pth, cook.py, and sitecustomize.py in site-packages, and a detached Python process holding a lock file at /tmp/remote_code_loader.lock.
What to do
- Don't run
pip installfirst. Python startup would re-run the malicious files. Remove them before touching the environment. - Delete the malicious files from every affected site-packages directory, and stop the background process.
- Reinstall pinned to a known-safe version. LiteLLM names 1.106.2 as the last safe release. Rebuilding virtual environments and images from scratch is better than patching them in place.
- Assume exfiltration if 1.107.0 ran on a machine with outbound internet access.
- Rotate everything that host could reach: the instance or task cloud role, every model provider key stored in the proxy's database, master and virtual keys, the database password, and any secret in the environment of processes on the host. Check cloud audit logs for those credentials being used from outside your infrastructure.
- Pin Docker images by digest, not by floating tags like
latest. LiteLLM corrected its floating tags later that day, but a digest is immune to tag changes.
What this says about AI infrastructure
Tools like LiteLLM sit in an unusually sensitive spot. A model gateway or proxy holds keys for several AI providers, often with generous spending limits and access to prompts and responses, so a compromise there is both a credential theft and a data exposure event. Teams adopting AI tooling quickly tend to treat these components as plumbing, when they deserve the care given to any system that holds production secrets.
The deeper lessons are about process:
- Revoke, don't just remove. Deleting a leaked secret from a repository's history does nothing if the secret still works. Rotate it the moment it's exposed.
- Tokens that can override protections are the real keys. Branch protection and approval gates only protect you if the credentials that can bypass them are scarce, short-lived, and watched.
- Pin dependencies, and know when something changes. An unpinned install during a two-hour window was enough.
If your team has adopted AI tooling faster than anyone has reviewed how it's deployed, scoped, and updated, a technical partner can help with that review: secrets hygiene, release pipelines, and dependency pinning, ideally worked through alongside your engineers rather than handed over as a report. It's one of the things our forward-deployed engineers do, and we've written about how that model works. The agent-safety questions raised by GitLab's AI Gateway flaw apply here too.