Compromised LiteLLM 1.107.0 Installed a Credential Stealer; PyPI Pulled It Within Two Hours
A compromised LiteLLM 1.107.0 release on PyPI installed a credential stealer and a backdoor that ran on every Python start. PyPI removed the release within two hours, and three versions are clean.

A compromised LiteLLM 1.107.0 release on PyPI installed a credential stealer and a remote code execution backdoor that ran every time Python started on a host, according to SafeDep's analysis. All seven wheels, covering Linux, macOS and Windows, carried the implant as three files in site-packages. The upstream GitHub source did not contain them.
PyPI removed the release by 13:23 UTC on Oct 21, 2026, less than two hours after the seven wheels were uploaded between 11:39 and 11:40 UTC, according to SafeDep's timeline. LiteLLM confirmed the compromise in an incident report, the analysis says. The clean versions are 1.106.2, 1.107.0rc1 and 1.107.0rc2.
What the malicious release did
The implant had two payloads. The first was a .pth file, cook.pth, which imports cook.py. Python executes lines beginning with import in .pth files at startup, so the stealer ran in every Python process on the host, including pip, IDE language servers and CI jobs, even when the process never imported LiteLLM itself.
cook.py collected SSH keys, cloud credentials, CI/CD secrets, AI developer tool tokens, browser passwords and the LLM provider keys stored in a LiteLLM proxy database. It encrypted the data and sent it to a lookalike domain, www.litellm[.]dev, per SafeDep. It also wrote a marker file so that it would run once per host.
The second payload, sitecustomize.py, started a background daemon. Every hour it read a server address from a GitHub file, ran the stealer again, and downloaded and executed code from that server. SafeDep says that GitHub account returned 404 at 13:40 UTC, about two hours after the release, so the backdoor no longer had a server address to follow. Hosts that ran the daemon before the deletion could have received second-stage code, and SafeDep could not recover the server address.
How the release was published
SafeDep says the attacker held the GitHub CLI credentials of three developers. LiteLLM's incident report, as cited by SafeDep, believes the attacker took them from the logs of an internal LiteLLM deployment exposed to the internet. With an organization owner's token, the attacker bypassed branch protection and pointed the private release workflow at a lookalike repository, Berri-AI/litellm. A second developer's credential then passed the approval gate, and the official pipeline built, signed and published the artifacts.
That sequence explains why the package looked legitimate. It was built and signed by the real release pipeline, not uploaded by an unknown account. The malicious change in the source distribution was a single added line in the build configuration, and no public commit in the official repository contains it, according to the analysis.
The removal timeline
All times are UTC on Oct 21, 2026, from LiteLLM's report as compiled by SafeDep. The attacker overrode branch protection at 10:08. A staging run built from the lookalike repository at 10:46. The malicious wheels were uploaded to PyPI at 11:39 and 11:40. Malicious Docker images were published at 11:46.
PyPI removed 1.107.0 at 13:23. The attacker's GitHub account returned 404 at 13:40. The Docker Hub tags were removed or repointed to clean images by 14:20. The affected Docker tags were v1.107.0, latest, main-latest and main-stable on Docker Hub and GHCR, with the code present between 11:46 and 14:20.
How to check an install
Start with the version. A Python environment that installed litellm==1.107.0 is the affected case. SafeDep lists the planted files as cook.pth, cook.py and sitecustomize.py in site-packages, plus the marker path shown in its indicator list and the environment variable PRIVCOLLECT_ACTIVE=1 in infected processes.
For Docker users, the check is the image digest, not only the tag, because tags were repointed. SafeDep publishes the malicious image index digest, and LiteLLM's incident report lists the same digest for the Docker Hub and GHCR images.
If the version and files match, treat the host as compromised rather than merely exposed. Uninstalling the package does not undo a credential theft that already happened, and the backdoor may have run before the GitHub file was deleted.
What to do next
Install a clean version: 1.106.2, 1.107.0rc1 or 1.107.0rc2. SafeDep also says the companion packages pinned by 1.107.0, litellm-proxy-extras==0.4.110 and litellm-enterprise==0.1.78, are clean.
Then rotate the secrets the stealer targeted: cloud credentials, SSH keys, CI/CD tokens, AI tool tokens, browser-stored passwords and the LLM provider keys held by the proxy. Check the proxy database for provider keys that were stored there. Review outbound connections to the lookalike domain and to the instance metadata address, both of which are in SafeDep's indicator list.
What is not known
No victim count was read. The analysis does not say how many installations pulled 1.107.0, whether any host received second-stage code before the server file was deleted, or who was behind the attack. SafeDep says it could not recover the server address. The LiteLLM incident report was referenced by SafeDep but was not opened directly for this article, so the remediation steps here come through that analysis.
A Hacker News thread on the analysis drew 478 points and 162 comments at the time of this run's capture. The visible discussion focused on detecting credential stealers, including canary tokens, and on key-vaulting mitigations. That is a sample of one thread, not a measure of how many organizations were affected.
A compromised 1.107.0 release installed a stealer and a backdoor on every Python start, PyPI removed it within two hours, and three versions are clean. The open question is how much credential material left the hosts that installed it before 13:23 UTC.