Skip to content
17 min read

LiteLLM supply chain attack and what to do now

Share

Por Lucas Andrade ·

LiteLLM supply chain attack on October 21, 2026 put malicious 1.107.0 on PyPI and Docker. See the UTC window, IoCs, and the pin to 1.106.2

In this article

LiteLLM supply chain attack activity on October 21, 2026 published version 1.107.0 with malware on PyPI and in Docker images. LiteLLM is a Python gateway that unifies language-model providers. The package often runs next to cloud keys and LLM credentials.

If your team installed that version or pulled official floating tags in the wrong window, the risk is not only the package itself. The payload also lands in the Python environment and can run on any interpreter start, even when nobody imports LiteLLM. Containment, hook cleanup, rebuilds, and rotation of reachable secrets therefore come first.

This guide stays in a defense and development lane. You leave with the UTC window and a clear perimeter, then with a way to prove exposure and decide what to rotate. After that you pin the litellm 1.106.2 safe version and separate what is still under investigation.

What happened, and what was the UTC window?#

On October 21, 2026, the LiteLLM publishing chain was compromised. Version 1.107.0 shipped with a credential stealer and a remote code loader. The bad artifact reached PyPI and official images.

What was the UTC window on PyPI and Docker?#

According to the official incident notice, updated on October 21, 2026 at 8:30 PM UTC, the package litellm==1.107.0 stayed live on PyPI for about two hours. The PyPI window ran from 11:39 AM UTC to 1:23 PM UTC. Docker Hub images tagged v1.107.0, latest, main-latest, and main-stable pointed at the compromised index from 11:46 AM UTC to 2:20 PM UTC.

The digest cited in the notice for the bad Docker Hub image is sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e. On GHCR, the matching tags were compromised from 11:46 AM UTC onward, and then became unavailable until about 1:51 PM UTC. The code tag v1.107.0 on the legitimate repository did not carry the malicious files. The installable artifacts therefore came from a repository controlled by the attacker.

Why was a clean Git tag not enough?#

Analysis from JFrog Security Research confirms that all seven wheels for 1.107.0 carried the payload. By contrast, the source tarball did not include the same three startup files. Teams that only review a Git tag or an sdist can therefore treat the release as clean while a bad wheel still lands on the host. The Register covered the same day as malware that steals secrets and delivers a RAT through PyPI and Docker registries.

In day-to-day response work, I most often see teams treat “two hours live” as too short for inventory. In CI with caches, automatic rebuilds, and pulls of latest, that window is enough to contaminate a runner, a notebook, and a proxy. The useful clock is the UTC time on the installer and the registry, not the office timezone.

Who is affected on PyPI and Docker, and who pins versions?#

You are inside the perimeter if you installed litellm==1.107.0 during the PyPI interval. You are also inside if you ran an image tagged v1.107.0, latest, main-latest, or main-stable during the Docker interval. Anyone who pins an older version and never pulled 1.107.0 in that window stays outside the bad artifact, yet still needs to validate lockfiles, caches, and local images.

The official notice separates open-source users from enterprise customers on the private registry. In OSS, unpinned pip or a floating image tag in the window should be treated as compromised. For enterprise, LiteLLM states that the private registry used for embargoed distribution was not affected. That claim holds only when the install truly came from that private channel. Otherwise public PyPI and public Docker Hub or GHCR tags share the same risk.

How people “fix versions” day to day also changes exposure. Dependabot, Renovate, a base image without a digest, and pip install -U litellm without a hash raise the chance of catching 1.107.0. Nobody needs to notice the version number in the moment. Datadog Security Labs summarizes the surface as the PyPI package plus GHCR and Docker Hub tags. It also notes high weekly download volume, which explains why inventory stays urgent even after a short exposure window.

ChannelBad artifactUTC window on 2026-10-21Minimum action
PyPIlitellm==1.107.0 (seven wheels)11:39 AM–1:23 PMTreat the host or venv as compromised if Python ran
Docker Hubv1.107.0, latest, main-latest, main-stable11:46 AM–2:20 PMCheck digest and pull time
GHCRsame tags on litellm, litellm-database, litellm-non_rootfrom 11:46 AM until unavailable ~1:51 PMRebuild from a good digest
Private enterpriseprivate registry (per LiteLLM)not listed as affectedConfirm the real artifact origin

The mistake that costs the most here is assuming “we do not use Docker, so we are fine,” or the reverse. LiteLLM PyPI compromised packages and LiteLLM Docker supply chain tags are parallel vectors of the same release. Inventory therefore needs to cross the lockfile, pip history, image digest, and the job’s UTC timestamp.

How do you know whether you installed the bad version?#

Start with install history and digests, not with team intuition. If pip show litellm pointed at 1.107.0 at any point in the window, treat the environment as compromised. The same rule applies when a container ran the compromised digest. That stance remains even after the package was removed from the public index.

Look for evidence of litellm-1.107.0.dist-info and of 1.107.0 wheels in cache. Also look for builds that installed the unpinned version between 11:39 AM UTC and 1:23 PM UTC on October 21, 2026. In containers, compare the pulled digest with sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e. Finding one of those signals confirms exposure. Finding nothing does not clear the environment, because /tmp cleanup, rebuilds, and volume rotation erase traces.

Socket reported that its scanner flagged the wheels minutes after publication. Image provenance also pointed at the lookalike repository Berri-AI/litellm, not the legitimate BerriAI/litellm. That helps explain why an “official” source tag can look clean while the installable artifact was not. If your pipeline only validates a Git tag, it could stay green and still deliver LiteLLM 1.107.0 malicious wheels.

Many people believe uninstalling the package erases the problem, and they are usually wrong, because the hooks landed in the root of site-packages. Version checks therefore need to travel with a hunt for cook.pth, cook.py, and unexpected sitecustomize.py. Without both axes, you close only half the inventory.

Which indicators of compromise do the official notice and analyses list?#

The most useful IoCs today mix startup files, artifacts under /tmp, an exfiltration domain, and the image digest. The official notice asks teams to search for litellm-1.107.0.dist-info, cook.pth, and sitecustomize.py. It also directs responders to kill the Python daemon holding /tmp/remote_code_loader.lock before any pip runs in a dirty environment.

JFrog publishes an operational list aligned with that picture. Signals include the domain www.litellm.dev and the path /healthcheck. They also include the dead-drop raw.githubusercontent.com/letters9813/pythonclient-test/main/domain.txt, the marker /tmp/.pc_once_72129118c59f5636c0bb, artifacts under /tmp/.pc_sq_ and /tmp/.pc_e_, and the affected image digest. According to The Register, Aikido’s hunting also highlighted /tmp/.pc_once_* as a sign that exfiltration had already fired. The loader lock, in turn, points to active or recent C2.

The mechanism matters for the hunt. cook.pth forces an import of cook.py at Python startup. sitecustomize.py starts the loader in the background. Any python, pip, or job in that venv can therefore retrigger the malware. In incident response, the wrong first reflex is to open the venv and “just run pip show.” If the dirty interpreter starts, you can re-execute the payload while you try to diagnose it.

Prefer shell and filesystem tools that do not invoke that Python. Isolate the machine and preserve DNS, proxy, and cloud logs before aggressive cleanup. Missing the lock on one host does not prove absence of LiteLLM credential theft, because ephemeral containers and /tmp cleanup remove evidence easily.

What secrets does the LiteLLM supply chain attack force you to rotate?#

If 1.107.0 ran on a host with internet egress, the official notice asks you to assume exfiltration may have occurred. The single-run marker confirms when it exists. Absence of the marker does not clear the host, because ephemeral containers and /tmp cleanup remove the proof.

The minimum list in the official statement includes the IAM role of the instance or task. It also includes every provider key stored in the LiteLLM proxy database, the master key and virtual keys, the password in DATABASE_URL, and any secret present in process environments on that host. LiteLLM then recommends checking CloudTrail for GetCallerIdentity from that role around install time, and for use of that material outside your infrastructure. For AWS flows, start with role assumption and identity calls around the install window so log triage stays ordered.

Analyses from Wiz and JFrog widen the inventory beyond the proxy. They describe collection of browser credentials, AWS, Azure, and GCP material, tokens and configs for AI tools, SSH and GPG keys, CI secrets, and readable environment variables. Wiz describes broad collection modules across browser, cloud, and AI services. Treat that as a strong surface hypothesis, not as proof that every module fired in your case. Rotation should still cover everything the host could reach, because leaving a live key usually costs more than rotating early.

When the environment looks like “just a prompt sandbox,” the risk barely changes if a real provider key, a cloud token, or a mounted ~/.aws volume was present. Rotate, revoke, and regenerate. Then audit use. Cleaning files without rotating secrets leaves the door open for whoever already received the encrypted package.

How do you pin the version and verify hash or signature?#

The safe version pointed to consistently by the official notice, JFrog, Endor Labs, and The Register is 1.106.2. The correct pin is not the first command, though. If the environment already executed 1.107.0, starting with pip install on the same Python can re-arm cook.pth and sitecustomize.py.

Why should you not start with pip install?#

Endor Labs stresses that the attack lives in packaging. A reviewed tag alone does not show the build change. Any command that starts the dirty Python can therefore re-arm the hooks. Diagnosis and remediation need to begin outside that interpreter.

Defensive order for containment and pinning#

Follow this defensive order, adapted from the official statement and JFrog’s notes:

  1. Isolate the host or container and preserve network, DNS, endpoint, and cloud logs before erasing useful evidence.
  2. Remove cook.pth, cook.py, sitecustomize.py, and matching *.pyc files under __pycache__ in each affected site-packages, using tools that do not start the compromised Python.
  3. Terminate the detached process tied to /tmp/remote_code_loader.lock and inspect markers /tmp/.pc_once_, /tmp/.pc_sq_, and /tmp/.pc_e_*.
  4. Rebuild the venv or image from scratch and pin litellm==1.106.2, preferably with the good wheel hash and an immutable good image digest.
  5. Only then rotate reachable secrets and audit later use of those secrets.

Checking hashes and signatures lowers recurrence, yet it does not replace a rebuild. Socket showed that build provenance can record a lookalike source that almost looks legitimate. Pinning by number without pinning by hash still leaves room for a swapped artifact in the next incident. Checking image digests, wheel hashes, and repository origin needs to become a release habit, not a ritual only after a scare.

The shortcut that most slows containment is “fixing in place” on the same dirty volume. Rebuilding from a verified artifact costs time now and avoids expensive false negatives later. When the choice is between cleaning and recreating, recreating wins for most AI proxies and runners.

Do open source and enterprise differ in this incident?#

Yes, and the difference comes from the distribution channel, not from magic immunity. LiteLLM states that customers on the private enterprise registry were not impacted by this public 1.107.0 release. Anyone who pulled from public PyPI or from public Docker Hub and GHCR tags enters the OSS scenario described in the notice.

There is an extra detail in the statement itself. The company mentions an embargoed release on the private channel tied to a vulnerability with disclosure planned for October 27, 2026. That item is independent of the 1.107.0 malware and should not be read as “enterprise is already patched for everything.” It only means the private registry was not the channel for the trojanized artifact in this incident, per the official source.

Datadog also notes that this is the second LiteLLM supply-chain compromise in 2026. At the time of their analysis, they had not established a link to the earlier episode their research associated with TeamPCP activity. Without a new primary source naming an actor for this October 21, 2026 case, defensive writing should speak of an attacker and a lookalike repository, matching the open-source consensus, and not of a specific named group.

In mixed operations, the practical risk is that an enterprise team assumes “we are customers, so we are done” while a parallel job still installs from PyPI. Confirm the real registry for each environment. If one cluster pulls from both worlds, the private-channel exemption does not cover the node that drank from the public source.

How do you reduce supply chain risk in AI dependencies?#

After containment, the gain is making the next artifact swap more expensive for the attacker and more visible to you. Exact version pins, hash pins in Python, immutable image digests, and a ban on latest in production are the floor. On top of that, block floating tags in CI for LLM gateways and require human review when a lockfile bumps a proxy that stores keys.

Monitor egress to lookalike domains and to raw GitHub dead-drops. In this case, the exfiltration domain cited by technical analyses was a close brand variation. Also treat startup hooks in site-packages as a persistence surface, especially when a payload survives removal of the main package. For the continuous process, a vulnerability management program needs to include AI dependencies with the same rigor applied to classic web libraries.

There is a clear limit. None of these controls eliminate supply chain risk. They shrink the window, raise detection odds, and reduce blast radius when a release token leaks. Separating environments that hold provider keys, using short-lived secrets, and avoiding notebooks with broad roles remain real defense, even with a package scanner in the pipeline.

The habit that most separates a mature team from a rushed one is refusing a “fast” rebuild with a moving tag after the incident. If yesterday’s fix used latest, the next bad 1.10x.y can enter through the same door. Artifact discipline is boring, and it is exactly what this case punished.

What is still unknown, and what should you monitor now?#

As of the official update on October 21, 2026 at 8:30 PM UTC, LiteLLM said it had identified the attack chain with high confidence. The investigation was still ongoing. The official account and open technical analyses describe artifacts built from the lookalike repository Berri-AI/litellm, not from the clean tag of the legitimate project.

Across the open sources checked for this article, there is still no classic CVE for a “code bug” in 1.107.0, because the core of the case is a trojanized artifact in the distribution chain. There is also no consolidated public attribution to a named group with a primary source for this specific event. Datadog states explicitly that a link to the earlier 2026 incident was not established in their text.

What to watch in the coming hours and days includes updates to the official notice, new IoCs, signs of reuse of secrets rotated late, and any second stage served by the remote code channel. JFrog warns that effects of arbitrary code downloaded after the dead-drop are not limited to the built-in stealer behavior. A host that kept the loader alive for hours therefore deserves broader forensics than “I only changed the version.”

Teams that wait for a final report before starting inventory often arrive after stolen keys have already been validated. Treat what is already consensus between the official notice and the labs as immediate action, and keep what is still uncertain in the investigation’s hypothesis board.

Frequently asked questions about LiteLLM supply chain attack#

This section answers real questions from people who run LLM proxies, CI, and notebooks on the same day as the incident. The answers below start from the LiteLLM notice of October 21, 2026 and from open technical analyses by JFrog, Datadog, Socket, Wiz, Endor Labs, and The Register. They do not replace forensics in your own environment, because cache, volumes, and pull timing change the framing of each host.

Do I need to rotate keys if I only tested the image and already deleted the container?#

Yes, if the container with the bad image actually ran and had network egress or mounts with secrets, rotation remains necessary. Deleting the container removes the ephemeral filesystem, yet it does not invalidate material that was already exfiltrated. The official notice is explicit about assuming exfiltration when 1.107.0 ran with internet access. Rotate provider keys, environment secrets, and reachable cloud credentials, then audit use outside the legitimate window.

Does a clean Git tag for 1.107.0 mean I can trust the release?#

No. The official notice and Socket show that the legitimate source tag did not contain the malicious files, while wheels and images were built from a lookalike repository. Trusting only the Git tag or the sdist was exactly the blind spot in this case. For installation, what matters is the wheel or digest the environment actually downloaded, with hash and origin confirmed.

Does uninstalling litellm with pip already remove the malware?#

In many cases that step is not enough as a first move, and it can be dangerous if the command starts the dirty Python. The files cook.pth, cook.py, and sitecustomize.py live in the root of site-packages and fire at startup. The converging guidance is to remove those hooks without invoking the affected interpreter, take down the loader, rebuild the environment, and only then install pinned 1.106.2. Treat a standalone uninstall as incomplete until you prove the hooks and /tmp artifacts are gone.

Are enterprise customers automatically safe?#

Only if the install came from the private registry that LiteLLM declares unaffected. If any enterprise environment also pulled public PyPI or public tags latest, main-stable, or main-latest in the October 21, 2026 window, that environment enters the same OSS playbook. The useful question is not the commercial contract. It is the real URL and digest of the artifact in each cluster.

What is the practical difference between this case and a code CVE?#

Here the central problem is supply chain of the published artifact, not a documented bug with a CVSS score in the clean tag’s code. Immediate actions therefore revolve around version inventory, digests, startup hooks, and secret rotation. Even without a classic CVE in the sources checked here, operational impact can be high, because the payload runs early and targets cloud and LLM credentials on the same host.

Conclusion#

If your environment touched 1.107.0 in the October 21, 2026 window, the order that best protects most teams is to isolate, remove hooks without re-arming Python, rebuild with hash-pinned or digest-pinned litellm==1.106.2, rotate everything the host could reach, and audit key use. Waiting for a perfect report before inventory only widens the time in which a live credential remains useful to whoever already collected the package.

The answer changes when you prove, with origin and timestamps, that you never installed the bad wheel and never pulled the floating tags in the Docker window. In that case hardening pins and monitoring still matters, yet forensic containment stops being the center. The first concrete step now is to list hosts, runners, and proxies with LiteLLM and mark which ones passed through pip or a pull between 11:39 AM UTC and 2:20 PM UTC on that day.

This article is informational and educational coverage of the LiteLLM supply-chain incident on October 21, 2026. It does not replace a professional security assessment, incident response, or forensics in your specific environment.

Perguntas frequentes

Do I need to rotate keys if I only tested the image and already deleted the container?
Yes, if the container with the bad image actually ran and had network egress or mounts with secrets, rotation remains necessary. Deleting the container removes the ephemeral filesystem, yet it does not invalidate material that was already exfiltrated. The official notice is explicit about assuming exfiltration when 1.107.0 ran with internet access. Rotate provider keys, environment secrets, and reachable cloud credentials, then audit use outside the legitimate window.
Does a clean Git tag for 1.107.0 mean I can trust the release?
No. The official notice and Socket show that the legitimate source tag did not contain the malicious files, while wheels and images were built from a lookalike repository. Trusting only the Git tag or the sdist was exactly the blind spot in this case. For installation, what matters is the wheel or digest the environment actually downloaded, with hash and origin confirmed.
Does uninstalling litellm with pip already remove the malware?
In many cases that step is not enough as a first move, and it can be dangerous if the command starts the dirty Python. The files cook.pth, cook.py, and sitecustomize.py live in the root of site-packages and fire at startup. The converging guidance is to remove those hooks without invoking the affected interpreter, take down the loader, rebuild the environment, and only then install pinned 1.106.2. Treat a standalone uninstall as incomplete until you prove the hooks and /tmp artifacts are gone.
Are enterprise customers automatically safe?
Only if the install came from the private registry that LiteLLM declares unaffected. If any enterprise environment also pulled public PyPI or public tags latest, main-stable, or main-latest in the October 21, 2026 window, that environment enters the same OSS playbook. The useful question is not the commercial contract. It is the real URL and digest of the artifact in each cluster.
What is the practical difference between this case and a code CVE?
Here the central problem is supply chain of the published artifact, not a documented bug with a CVSS score in the clean tag’s code. Immediate actions therefore revolve around version inventory, digests, startup hooks, and secret rotation. Even without a classic CVE in the sources checked here, operational impact can be high, because the payload runs early and targets cloud and LLM credentials on the same host.

Share

Share

Related posts

No comments yet

Be the first to comment.

Leave a comment

Sign in with your Canverly account to comment. You can use the same account on any site in the network.

Sign in with Canverly