Article
LiteLLM 1.107.0 Supply Chain Attack: Timeline, Stolen Data and a Response Checklist
LiteLLM 1.107.0 on PyPI and Docker carried a credential stealer on 21 October 2026. See the timeline, what it took and a checklist to…
Quick links
Press Enter to search, Esc to close
Significant cyber incident
On 21 October 2026 a malicious LiteLLM 1.107.0 was published to PyPI and to the project's Docker image tags.
In short
On 21 October 2026 a malicious LiteLLM 1.107.0 was published to PyPI and to the project's Docker image tags. LiteLLM says its release pipeline was compromised through developer credentials that appear to have been stolen GitHub CLI OAuth tokens. The release carried a credential stealer that runs on every Python start and a loader that runs remote code. No actor has been named in the sources we opened.
LiteLLM says its release pipeline was compromised and that version 1.107.0 reached PyPI and Docker registries with malware. The official v1.107.0 source tag on GitHub does not contain the malicious files, according to LiteLLM. Seven wheels were uploaded to PyPI between 11:39:51 and 11:40:13 UTC, and the Docker image was published at 11:46:56 UTC.
PyPI removed the release at 13:23 UTC, per LiteLLM. LiteLLM says the affected GHCR tags were unavailable by 13:51 UTC and that all affected Docker Hub tags were removed or repointed to clean artifacts by 14:20 UTC. Its enterprise private release was not affected.
Times differ between sources. Wiz writes that the release was quarantined on PyPI “as of 1:20 UTC”. That is before the 11:39 upload, so it most likely means 13:20 UTC. Wiz also says the images were removed around 13:53 UTC. StepSecurity says BerriAI confirmed the images gone at 14:32 UTC. We use LiteLLM’s own times above and say where others differ. Our news post has a LiteLLM 1.107.0 response checklist.
LiteLLM’s response: on 21 October 2026 it removed the packages from PyPI, Docker Hub and GHCR and revoked the tokens involved. It removed all but one unaffected user from its GitHub organization. It also removed trusted publishing links to the organization from public registries and restored the release workflow. It promised updates every two hours. PyPI marked release 1.107.0 as quarantined, and the project page shows the badge “Release quarantined on Oct 21, 2026”. SafeDep reports that the account hosting the dead-drop file and its repository were deleted in the afternoon.
StepSecurity reports that the domain litellm[.]dev was registered at this time.
Wiz and StepSecurity report ten attacker commits pushed to the lookalike repository Berri-AI/litellm.
LiteLLM says GitHub branch protection rejected a change to the private release workflow, then a privileged developer credential overrode the protection and applied it.
LiteLLM says the modified workflow ran a staging build from the attacker-controlled repository Berri-AI/litellm.
LiteLLM says a second developer credential satisfied the production approval gate.
Seven malicious litellm 1.107.0 wheels are uploaded to PyPI (11:39:51 to 11:40:13, per LiteLLM).
Container publish jobs run and the Docker image contains the malicious content, per LiteLLM.
LiteLLM says a third developer credential deleted production and staging workflow records.
GitHub issue 47826, reporting the compromise, is opened in the BerriAI/litellm repository; StepSecurity lists the same time.
PyPI removes litellm 1.107.0, per LiteLLM.
Affected GHCR tags are unavailable, per LiteLLM; Docker Hub tags still pointed to the bad image index at that time.
All affected Docker Hub tags are removed or repointed to verified clean artifacts, per LiteLLM.
LiteLLM says three engineers’ GitHub accounts were used, apparently through stolen GitHub CLI OAuth tokens. One account changed the release pipeline and triggered the run, another approved it and a third deleted workflow records. LiteLLM says it has not yet found how the tokens were obtained.
Socket and Wiz add that the build came from a lookalike repository, Berri-AI/litellm, one hyphen away from the real BerriAI/litellm. SafeDep shows that a build setting added a folder named cook to the wheels but not to the source archive. SafeDep rates as moderate to high confidence that the wheels came from attacker-modified source built by the project’s own release pipeline.
The wheels install three files into site-packages: cook.pth, cook.py and sitecustomize.py. The .pth file imports cook at every Python start, using Python Startup Hooks (T1546.018), so no import of litellm is needed. The stealer reads cloud, developer, CI and AI tool credential files and environment variables (Credentials in Files, T1552.001). When a database URL is set, it also reads the LiteLLM proxy tables that hold provider keys.
It encrypts the bundle and posts it to www.litellm[.]dev/healthcheck. The sitecustomize.py file starts a detached loader that checks a GitHub dead-drop file for a domain, then fetches and runs code from it. StepSecurity says the loader fails silently on Windows, while the stealer still runs.
This is a case of Compromise Software Supply Chain (T1195.002). Socket maps it to T1195.001, T1546.018 and T1552.001, among others.
No government or security company has named an actor in the sources we opened (LiteLLM, Wiz, Socket, SafeDep and StepSecurity). LiteLLM's own post names no actor and says it has not yet identified how the tokens were obtained. CERT-EU reported that the cybercrime actor TeamPCP compromised LiteLLM in March 2026, using the word "reportedly". Nothing in the October sources links the two events, so we do not make that link.
No count of installs or affected companies has been published in the sources we opened. LiteLLM says to assume compromise if 1.107.0 ran in an environment, or if a container ran the affected image digest. Wiz reports that about 4.5 hours after exfiltration the attacker validated AWS instance role credentials from two IP addresses. The calls were sts:GetCallerIdentity and then Bedrock model listing, which Wiz calls consistent with LLMjacking. Wiz says some environments also saw IAM enumeration.
LiteLLM says a privileged credential overrode protection that had just rejected the change. A control that one credential can bypass is a single point of failure.
A second developer credential satisfied the production gate. If tokens are stolen, two approvers can mean two stolen tokens.
LiteLLM and SafeDep both say the GitHub tag was clean while the wheels were not. Compare what you install with the source it claims to come from.
The payload ran whenever Python started, even in programs that never imported litellm, so any script on the host could trigger it.
Socket says removing the package does not reverse credential exposure or stop a loader that already runs.
Search lockfiles, caches, build logs and running containers for litellm 1.107.0. Also search for the image digest LiteLLM lists for the affected index: sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e.
Search site-packages for litellm-1.107.0.dist-info, cook.pth, cook.py and sitecustomize.py. LiteLLM says finding none does not prove the environment is clean.
Look for a process that holds /tmp/remote_code_loader.lock and end it; StepSecurity puts this step first. Do not run pip install first, because Python startup re-runs the files.
StepSecurity and Socket list litellm[.]dev, requests to its /healthcheck path and any /codepy request. A /codepy request means second-stage code ran.
LiteLLM lists the instance or task role, every provider key in the proxy database, master and virtual keys, the database password and any secret in process environments.
LiteLLM says to audit CloudTrail for GetCallerIdentity from the instance role around install time and for use of its credentials from outside your infrastructure.
Only litellm 1.107.0 on PyPI, in all seven wheels, and the Docker tags v1.107.0, latest, main-latest and main-stable. SafeDep lists 1.106.2, 1.107.0rc1 and 1.107.0rc2 as clean.
LiteLLM names litellm 1.106.2, or any explicit version published before the incident. Socket adds that its investigation did not certify every earlier artifact.
Possibly. SafeDep says the .pth file runs when any Python process starts on the host, even one that never imports litellm.
The sources we opened give no CVE id and no GitHub advisory number for it.
No actor has been named in the sources we opened. LiteLLM says it has not yet found how the developer tokens were obtained.
In March, LiteLLM says versions 1.82.7 and 1.82.8 were uploaded straight to PyPI outside its normal workflow. Both carried a stealer, and 1.82.8 also added a litellm_init.pth file. In October, LiteLLM says its own release pipeline built the bad version from a lookalike repository, and the Docker tags were hit too.
Take control of your digital security with an exclusive demo of our AI-driven threat intelligence platform.