AI
The LiteLLM 1.107.0 Backdoor and the AI Keys It Went After
For about two hours on October 21, 2026, installing LiteLLM from PyPI meant installing a credential stealer and an hourly remote code loader. This guide explains what the payload did, who is exposed, and the concrete steps to check, rotate and harden your AI tooling.
Optinode Team · · 9 min read

What happened on October 21
Early on October 21, 2026, an attacker got into LiteLLM's release pipeline and published version 1.107.0 to PyPI and to the official Docker registry with compiled malware inside. According to LiteLLM's own incident report, the malicious PyPI package was live from roughly 11:39 to 13:23 UTC. That sounds short. For a library that sits in CI pipelines with unpinned dependencies, two hours is plenty.
The Docker side stayed exposed longer. Wiz reports that the trojanized build was published on GHCR and Docker Hub under the v1.107.0, latest, main-latest and main-stable tags, and Rescana's timeline summary puts the window for those tags at 11:46 to 14:20 UTC. If your deployment pulls latest on restart, a routine rollout that afternoon was enough.
How did it get in? Per BerriAI, as reported by Cycode, the attacker used stolen GitHub CLI OAuth tokens from three engineers: one account triggered the release workflow and another approved it. StepSecurity adds that the release was built from a lookalike GitHub repository, which The Register says Wiz traced to a hyphenated imitation of the real organization named Berri-AI. A two-person approval rule did not help, because both people were the attacker.
LiteLLM states that all earlier versions are safe, that 1.106.2 is the last safe release, and that customers on its private enterprise release were not affected. There is no CVE for the incident, which matters if your scanning relies on CVE feeds to tell you something is wrong.
Why it runs even if your code never imports LiteLLM
This is the detail that changes the risk calculation. SafeDep found that all seven 1.107.0 wheels, covering Linux, macOS and Windows, drop three files into site-packages that are not present in the upstream GitHub source. Both payloads run whenever any Python process starts on the host.
The files are cook.pth, cook.py and sitecustomize.py, as this technical breakdown documents. Python processes .pth files and sitecustomize.py automatically at interpreter startup, so the malware does not care whether your application calls LiteLLM. A data science notebook, a cron script or a test run on the same machine all trigger it.
OX Security puts it plainly: having the package installed is enough to be affected. That includes the case where LiteLLM arrived as a dependency of something else and nobody on the team knew it was there. In practice, this is the scenario I would worry about most, because the team that owns the box may not even think of itself as an AI team.
What the payload stole and where it sent it
The stealer, cook.py, is broad. SafeDep lists SSH keys, cloud credentials, CI/CD secrets, AI tool tokens, browser passwords, and the LLM provider keys stored in a LiteLLM proxy database. That last item is the reason this attack targeted LiteLLM specifically.
LiteLLM Proxy keeps upstream provider keys in a Postgres table, and Cycode reports that the malware queried that table to pull up to 500 of them. A gateway is useful precisely because it centralizes every provider key your company uses. That also makes it the single most valuable place to rob.
JFrog's analysis shows the stolen data was encrypted with AES-256-CBC, the key wrapped with an embedded RSA-4096 public key, and the archive sent over plain HTTP to www.litellm[.]dev/healthcheck. The lookalike domain was registered on October 13, 2026, eight days before the release. The real project uses litellm.ai.
The second payload is arguably worse. sitecustomize.py starts a background process that every hour reads a server address from a GitHub file, reruns the stealer, and downloads and executes code from that server. The GitHub account behind that address returned 404 at 13:40 UTC, but hosts that ran the loader earlier may already have received second-stage code. Rescana also notes that Wiz saw stolen credentials being abused starting about 4.5 hours after exfiltration, so the clock on rotation is measured in hours, not days.
Who is actually exposed
LiteLLM is BerriAI's Python SDK and proxy that puts more than 100 LLM providers behind one OpenAI-compatible API. As StepSecurity notes, it runs on developer laptops, in CI pipelines, and on production gateways that hold keys for OpenAI, Anthropic, Azure, Bedrock and Vertex. Each of those environments has a different blast radius.
If you are not sure whether any of these apply to you, assume one of them does until you have checked. The point of a gateway is that it disappears into the plumbing, and that is exactly why many teams will not remember installing it.
Who is probably fine: teams that pinned an earlier version with hashes, teams on LiteLLM's private enterprise release, and container users who pin images by digest rather than tag. Who is not fine just because they never pulled 1.107.0 into production: anyone whose CI or laptops resolved the latest version during the window.
- Developer machines where someone ran pip install or upgraded dependencies that afternoon, exposing SSH keys, browser passwords and local cloud profiles.
- CI runners that install unpinned requirements, exposing pipeline secrets, deploy tokens and registry credentials.
- Production proxy containers built from or restarted on the latest, main-latest or main-stable tags, exposing the provider key table and the instance's cloud role.
- Any host where LiteLLM is a transitive dependency of another AI tool, agent framework or internal package, even if no code calls it.
First hour: checking whether you were hit
Start with the cheap, definitive checks before you open a full incident. Aikido's Ilyas Makari told The Register that two files show whether exfiltration fired and whether the command-and-control daemon ran. The same check applies to anyone who ran the 1.107.0 image or pulled the affected tags.
For containers, Chainguard recommends listing LiteLLM images by digest and comparing them with the published bad digests. Tags lie after the fact; digests do not. Then go to the network layer, using the indicators Kodem Security published.
A clean result on one host tells you little about the others. Run the checks across every laptop, runner and container that could have resolved the package, not just the production gateway.
- Look for /tmp/.pc_once_* (exfiltration fired) and /tmp/remote_code_loader.lock (loader daemon ran) on every candidate host.
- Check site-packages for cook.pth, cook.py and an unexpected sitecustomize.py.
- Run pip show litellm or inspect lockfiles and build logs for 1.107.0 resolved on October 21.
- Search DNS and proxy logs for www.litellm[.]dev and the path letters9813/pythonclient-test.
- Look for POST requests to www.litellm[.]dev/healthcheck carrying the header X-Token: XWiA8gZNa7NcX2XRoAEb and an old MSIE 7.0 user agent.
- In cloud audit logs, look for STS GetCallerIdentity calls from a LiteLLM host's instance role around install time.
Contain, rebuild and rotate
If any indicator matches, treat the host as compromised. That is LiteLLM's own guidance, and it is the right call: a remote code loader ran for an unknown period, so you cannot know what else was dropped. Uninstalling the package and moving on is not a remediation.
Chainguard's sequence is sensible: stop any detached Python process holding /tmp/remote_code_loader.lock, block outbound traffic to the exfiltration domain and the dead-drop URL, and keep the logs for the investigation. Socket adds that teams should stop deploying 1.107.0 and investigate every environment where Python ran after installation, including proxy containers and CI runners.
Rotation is where most teams cut corners. Rotating the LiteLLM master key does nothing if the attacker already has the upstream OpenAI or Bedrock keys from the database. You have to revoke at the provider, for every key that was in the table.
- Isolate affected hosts and rebuild them from a known clean image rather than cleaning in place.
- Redeploy LiteLLM pinned to 1.106.2, referenced by version and, for containers, by digest.
- Revoke and reissue every LLM provider key stored in the proxy database, at the provider's console.
- Rotate cloud credentials and instance role sessions, SSH keys, CI/CD secrets, GitHub and registry tokens found on affected hosts.
- Treat browser-saved passwords on affected laptops as exposed and reset them.
- Review provider usage and cloud logs for activity after the exfiltration time, keeping in mind that abuse was seen within hours.
The longer fix: inventory, pin and isolate
The uncomfortable lesson is that many companies route every AI call, and every API key, through a library their security team has never reviewed. The first job is simply knowing where it lives. Generate a dependency inventory from lockfiles and container images across all repos, and search specifically for AI gateways and SDKs, including transitive ones.
Pinning is not glamorous, but it is the control that demonstrably worked. In March, the maintainers noted that Proxy Docker image users were unaffected because dependencies were pinned in requirements.txt, per the GitHub incident thread. Pin exact versions with hashes, pin images by digest, and stop deploying latest tags to production. A short delay before adopting new releases would also have helped: Socket's scanner flagged the wheels seven minutes after publication, so even a one-day cooling period beats instant auto-updates.
Finally, rethink where secrets sit. A gateway that stores hundreds of provider keys in a database on the same host that runs arbitrary Python is a concentration risk. Keep provider keys in a secrets manager with scoped, short-lived access, give the gateway's cloud role only what it needs, and restrict outbound network traffic from gateway hosts to the providers they actually call. An egress allowlist would have blocked a plain HTTP POST to an unknown domain.
- Inventory: list every AI SDK, gateway and agent framework in lockfiles and images, direct and transitive.
- Pin: exact versions with hashes for Python, digests for containers, no latest in production.
- Delay: let new releases age before automated upgrades pick them up.
- Isolate: separate developer AI tooling from machines holding production credentials.
- Scope: per-provider, per-environment keys with spend limits, so one leak does not expose everything.
- Restrict egress: gateway hosts should only reach known provider endpoints.
Second time this year, and what it says about AI plumbing
This is not LiteLLM's first bad release of 2026. In March, an attacker took over a maintainer's PyPI account and published 1.82.7 and 1.82.8 on March 24; the issue thread links the stolen PyPI credentials to the earlier Trivy compromise, and PyPI suspended the whole package while maintainers rotated accounts. Cycode describes that as the PyPI phase of a TeamPCP campaign that began in late February.
OX Security notes that the October attacker used different tooling and infrastructure. The entry point also moved: March went through a publishing account, October went through the release pipeline using engineers' GitHub tokens and a lookalike repository. Fixing one path did not close the other.
I would not read this as a reason to rip out LiteLLM specifically. Any popular gateway holding many provider keys is an attractive target, and the maintainers disclosed quickly and in detail. The better takeaway is that AI infrastructure now deserves the same supply-chain discipline as payment or identity code. If your AI gateway can be updated by an unattended pip install, you have already accepted this risk; the question is whether you knew it.
Frequently asked questions
- Which LiteLLM versions are affected?
- Only 1.107.0, on PyPI and in the Docker images tagged v1.107.0, latest, main-latest and main-stable during the window on October 21, 2026. LiteLLM says all earlier versions are safe and names 1.106.2 as the last safe release. The separate March 2026 compromise affected 1.82.7 and 1.82.8.
- I never import litellm in my code. Am I still at risk?
- Yes, if the package was installed. The malicious wheels dropped a .pth file and sitecustomize.py that run on every Python interpreter start, so any Python process on the host triggered the stealer and the loader. Check for it as a transitive dependency too.
- Is uninstalling 1.107.0 enough?
- No. The hourly loader could download and run second-stage code, so a host that ran it should be treated as compromised and rebuilt from a clean image. You also need to rotate every credential that was reachable from that host, especially the upstream LLM provider keys.
- How quickly do I need to rotate keys?
- As fast as possible. Wiz observed stolen credentials being abused starting about 4.5 hours after exfiltration, so if you confirm exposure, revoke provider keys and cloud credentials before finishing the full investigation.
- Is there a CVE I can track for this?
- There is no CVE for the incident. If your vulnerability tooling depends on CVE feeds, it may not flag 1.107.0, so check versions, image digests and the published indicators directly.
Sources
- Contained: Oct 21, 2026 LiteLLM release v1.107.0 Compromised
- LiteLLM Compromised, Steals Credentials (Wiz)
- LiteLLM 1.107.0 Supply-Chain Compromise: Credential-Stealing Release Hit PyPI and Docker. Isolate, Rebuild and Rotate Now (Rescana)
- LiteLLM 1.107.0: Stopping a Poisoned Package Before It Installs (Cycode)
- litellm 1.107.0 Compromised on PyPI: Backdoored Wheels Drop a Credential Stealer and an Hourly Remote Code Loader (StepSecurity)
- LiteLLM supply chain attack hoovers up passwords and secrets (The Register)
- Compromised LiteLLM 1.107.0 on PyPI Installs a Credential Stealer and Backdoor (SafeDep)
- LiteLLM 1.107.0 Compromised on PyPI: How to Check and What to Rotate
- LiteLLM 1.107.0 Compromised With A RAT InfoStealer (OX Security)
- LiteLLM Hijacked Again: Malicious 1.107.0 Wheels Steal Credentials and Load Remote Code (JFrog Security Research)
- LiteLLM attacked again: Malicious 1.107.0 wheels on PyPI and Docker Hub (Chainguard)
- LiteLLM supply chain attack: affected versions, IOCs and first-hour response runbook (Kodem Security)
- LiteLLM PyPI Package and Docker Images Compromised to Steal Cloud and AI Credentials (Socket)
- [Security]: litellm PyPI package (v1.82.7 + v1.82.8) compromised — full timeline and status · Issue #24518 · BerriAI/litellm
- Shedding The Lite: Unfolding The Dramatic Turn of Events with the LiteLLM Compromise (Cycode)


