// threat intel

LiteLLM Supply Chain Attack: Poisoned 1.107.0 Hit PyPI and Docker Hub

LiteLLM supply chain attack: poisoned 1.107.0 on PyPI and Docker Hub stealing AI and cloud credentials

The LiteLLM supply chain attack put a signed but malicious version 1.107.0 on PyPI and Docker Hub for about three hours on October 21, 2026. According to SecurityWeek, that was long enough for an estimated 49,000-plus downloads. Any team that routes OpenAI, Anthropic or Bedrock traffic through LiteLLM needs to check whether that build ran and which keys it could reach.

Key takeaways

  • LiteLLM 1.107.0 on PyPI and Docker Hub was malicious for about three hours on October 21, 2026, with an estimated 49,000+ downloads per SecurityWeek; 1.106.2 is the latest clean release.
  • Attackers used leaked GitHub CLI OAuth tokens to disable branch protection and point the release workflow at the lookalike repo Berri-AI/litellm, so the pipeline signed and published the malware.
  • The payload is a stealer plus RAT that runs on every Python interpreter start and targets cloud, AI-provider, GitHub, SSH, GPG and browser secrets.
  • Wiz saw stolen keys abused about 4.5 hours after theft, including Amazon Bedrock queries consistent with LLMjacking.
  • There is no CVE; enterprise customers on LiteLLM's private repository were not affected, but mirrors and cached container digests still need checking.

What happened to LiteLLM on October 21, 2026?

LiteLLM version 1.107.0 was malicious. On October 21, 2026, attackers published a poisoned build of the open-source LLM proxy to both PyPI and Docker Hub. Anyone who installed or pulled that version during a window of roughly three hours received an information stealer and a remote-access trojan in the same payload.

SecurityWeek reported the incident on October 23 and cited an estimate of more than 49,000 downloads before the release was taken down.

LiteLLM is easy to overlook. It exposes one OpenAI-compatible endpoint in front of OpenAI, Anthropic, Amazon Bedrock, Azure and dozens of other providers, and it handles keys, routing, budgets and logging centrally. That popularity is exactly what made it worth poisoning. A typical LiteLLM host holds the API key for every model provider the company pays for, usually alongside cloud credentials and deployment tokens.

To contain the incident, the maintainers removed the package from PyPI. On Docker Hub, the affected tags and image variants were either deleted or repointed to clean images. The latest clean release is 1.106.2.

Spread evenly over the window, the estimate works out to more than 16,000 downloads per hour. That rate suggests CI pipelines, container rebuilds and autoscaling nodes resolving “latest” without a pin, not thousands of engineers typing pip install by hand. The real split between humans, build agents, mirrors and repeat pulls has not been published.

Two clarifications matter for scoping:

  • There is no CVE or CVSS score. This was a compromised release, not a flaw in a code path. A vulnerability scanner keyed on CVE identifiers may not flag it, so check versions and digests directly.
  • This is not the Trivy incident. In an earlier, unrelated case, LiteLLM was initially suspected in a compromise affecting about 2,500 organizations, and the trail later led to Trivy. Do not merge the two in your incident notes.

How did attackers publish a signed LiteLLM release?

They took over the project’s own release machinery, so the pipeline signed and published the malware as if it were a normal release. LiteLLM’s investigation traces the entry point to GitHub CLI OAuth tokens belonging to what the project called “an unexpected, innocuously named user account in our internal LiteLLM deployment, which was exposed to the public internet.”

How those tokens leaked is the most uncomfortable part of the story. LiteLLM says they were likely leaked by Claude Code, which under specific circumstances embedded them in a response body. That response may then have been written to LiteLLM’s logs, where the attackers probably found it.

This is LiteLLM’s assessment. No CVE, advisory or confirmation from Anthropic has been cited, so treat it as a working hypothesis rather than an established bug. LiteLLM also says it is still unclear how the attackers reached the internal deployment or moved laterally. What is known is that they ended up holding three sets of developer GitHub CLI credentials.

The attackers then worked through the release process step by step:

  1. They disabled branch protections on the repository.
  2. They merged a change that pointed the releaser at a different source repository.
  3. They ran a compromised GitHub workflow aimed at a lookalike repository, Berri-AI/litellm, one hyphen away from the legitimate BerriAI/litellm.
  4. They let the trusted pipeline sign the resulting artifacts and publish them to PyPI and Docker Hub.

That last step explains why signing did not stop the attack. A signature or build-provenance record tells you which identity or workflow produced an artifact. It says nothing about whether the source code fed into that workflow was benign. Once an attacker controls an authorized release workflow, they get correctly signed malware without touching any cryptography.

Every technique in this chain is mundane. None needed a zero-day: leaked tokens in logs, an internal service reachable from the internet, branch protection that a developer token could switch off, and a release job that trusted whatever repository it was told to build from.

What does the LiteLLM 1.107.0 malware do on a host?

It steals almost every secret a developer or server holds, then stays behind as a remote-access trojan. The stealer collects:

  • system information and environment variables
  • browser credentials and cookies
  • developer credentials, shell history files, SSH private keys and GPG keys
  • cloud secrets for AWS, Google Cloud and Azure
  • AI tool API keys, including Anthropic, GitHub Copilot and OpenAI, with other providers also targeted

The data is encrypted and sent to a lookalike domain posing as the LiteLLM project. We are not reproducing the indicator here; take it from the LiteLLM, Wiz and StepSecurity write-ups.

The persistence design turns a three-hour exposure into a much longer problem. The payload drops three files into the site-packages root so they execute whenever a Python interpreter starts, not only when an application imports LiteLLM. That behavior matches Python’s .pth startup-file mechanism, which the site module processes on every interpreter launch.

So the code runs when someone starts pip, pytest, a Jupyter kernel, a cron job or an unrelated service sharing the same environment. Removing LiteLLM from requirements.txt does nothing for an environment that already has those files.

The RAT component, according to StepSecurity, “checks a GitHub dead drop every hour and runs whatever Python the attacker serves,” in addition to checking in with a command-and-control server. Using GitHub as a dead drop is deliberate. Outbound traffic to github.com is normal on almost every developer laptop and build agent, so egress filtering and proxy logs are unlikely to flag it.

LiteLLM also described the malware as likely built with AI assistance. No technical evidence for that has been shared, and it changes nothing about detection or cleanup.

Why the 4.5-hour gap matters for LLMjacking

Stolen keys were in use before most victims could have known they were victims. Wiz observed the attackers abusing exfiltrated credentials about 4.5 hours after theft. That is under a single working afternoon, and shorter than the time many teams need to notice an upstream advisory, let alone finish rotating secrets.

One of the first things Wiz saw was stolen AWS credentials querying Amazon Bedrock models. That fits LLMjacking: using someone else’s cloud account to consume paid model capacity. Bedrock bills per use, so unauthorized model invocations land directly on the victim’s invoice.

The goal is often resale of model access rather than data theft. But a key that can call Bedrock can usually do more, and depending on configuration, prompts and logged responses can expose business data as well.

In Cyprus, LiteLLM shows up in exactly the places this payload targets. EMI and payment firms use it to put customer-support and transaction-review assistants behind one gateway. iGaming operators use it to route content and risk models across providers. Engineering teams in Limassol use it as an internal gateway so developers never handle raw provider keys.

Each of those setups concentrates OpenAI, Anthropic and Bedrock keys on one host, usually with an IAM role or access key that can do more than call models. That is the blast radius to plan for.

What should you remove, rotate and record?

Confirm whether 1.107.0 ever ran, contain affected hosts, revoke every credential they could reach, and record each step. That order holds up both technically and in front of a supervisor.

1. Find every place 1.107.0 could have landed

Exposure depends on where you pulled from:

  • Public PyPI or Docker Hub consumers who resolved 1.107.0 during the window are in scope, including production proxies, CI runners and developer laptops.
  • Enterprise customers pulling from LiteLLM’s private repository were not affected, according to LiteLLM.
  • Internal mirrors and caching proxies are a gray zone. If your Artifactory, Nexus or registry mirror fetched 1.107.0 during those three hours, it may still be serving it.

A version check on today’s production image is not enough. Search lockfiles, pip caches, CI build logs and container registries for 1.107.0 resolved on or around October 21. For containers, work from image digests, not tags.

A tag is a movable pointer. Repointing it on Docker Hub does not change images already cached on Kubernetes nodes, on developer machines or baked into your own downstream builds. A clean tag can give false reassurance while a node keeps running the poisoned digest.

Then check whether an affected interpreter or container actually started. Look for unexpected files in the site-packages root, unexplained Python processes and outbound connections matching the vendor indicators.

2. Isolate before you rotate

Rotating secrets on a host that still runs a stealer gives the attacker your new secrets. Isolate affected machines first, and preserve logs and images if you may need forensic evidence. Do the rotation from a known-clean workstation. Then rebuild affected environments from scratch on 1.106.2, pinned by hash or digest.

3. Rotate means revoke

If 1.107.0 was present during the window, treat everything that host or user could see as exposed: AWS, Azure and GCP keys; Anthropic, OpenAI and Copilot keys; GitHub tokens, CI secrets, SSH and GPG keys; and browser sessions.

Writing a new value into an environment variable does not invalidate the old one. Revoke old keys, kill active sessions and reissue tokens. Then review CloudTrail, GitHub audit logs and provider usage dashboards for activity after October 21.

On AWS, look specifically for Bedrock InvokeModel or Converse calls from unfamiliar sources or regions, and for billing spikes. Our AWS penetration testing work routinely shows that one leaked access key reaches far more than its owner expects.

4. Write it down for NIS2 and DORA

For regulated Cyprus firms, a confirmed compromise is a reporting question as well as a patching one. Under NIS2, a significant incident generally requires an early warning within 24 hours, a notification within 72 hours and a final report within a month. DORA requires financial entities to classify ICT-related incidents and report major ones.

In both cases, keep a timeline, the list of hosts and digests, every revoked credential with a timestamp, and the evidence showing whether the payload executed. The same record feeds your third-party risk register, because LiteLLM is now a supplier with a documented incident.

If your incident classification process has never been tested against a supply-chain case like this, our NIS2 and DORA readiness review covers it.

Practitioner’s note: On AI engagements, the LiteLLM or gateway host is often the least-governed box in the estate. One engineer usually set it up during a pilot and gave it an IAM role broad enough that nobody had to revisit it.

Its request logs often capture full prompts, headers and, as this case shows, occasionally tokens. Before you close this incident, check who can read those logs, whether the admin UI is reachable from the internet, and what the attached cloud role can do besides call models.

A clean reinstall plus credential revocation is not proof of eradication. Close the incident only after EDR findings, outbound traffic and post-incident cloud and GitHub activity all come back clean.

What is still unknown, and what to fix in your own pipeline

Several basics are still open: how the attackers first reached LiteLLM’s internal deployment, how they moved from there, who they are, and how the 49,000 downloads break down. No attribution, victim geography or sector data has been published. The Claude Code token-leak explanation remains LiteLLM’s likely cause, not a confirmed vendor bug.

The lessons for your own build process do not depend on those answers. An internal service exposed to the internet, tokens ending up in application logs, developer credentials able to disable branch protection, and a release job that does not check which repository it builds from would all be findings in a pentest of a Cyprus fintech pipeline.

Lookalike namespaces such as Berri-AI versus BerriAI are the same trick we covered in the fake Twilio bug bounty npm package. They work because a hyphen is easy to miss in a pull request diff.

For teams building on LLM gateways, agents and model SDKs, an AI supply chain security audit checks the controls this attack exploited: version and digest pinning, private mirrors with a quarantine period, provenance checks on the source repository rather than just the signer, log redaction and the scope of keys held by AI infrastructure.

FAQ

Was every LiteLLM version compromised or only 1.107.0?

Only 1.107.0, distributed through PyPI and Docker Hub on October 21, 2026, has been identified as malicious. The latest clean version is 1.106.2.

Are Docker images that were retagged still safe to pull?

A fresh pull of a repointed tag should now return a clean image, but a tag is only a pointer. Images already cached on nodes, laptops or in your own registry keep the poisoned digest, so check digests, not tags.

Did the malware run only inside the LiteLLM process?

No. It drops three files into the site-packages root that execute whenever a Python interpreter starts in that environment, including pip, test runners and unrelated scripts.

Should we rotate Amazon Bedrock and other model keys even if we saw no alerts?

Yes, if 1.107.0 was present during the window. Wiz saw stolen credentials abused within about 4.5 hours, so revoke old keys and sessions rather than waiting for an alert.

Does a private LiteLLM enterprise repository mean we can skip the check?

LiteLLM says enterprise customers pulling from its private repository were not affected. Still confirm that no build, mirror or developer machine resolved the public 1.107.0 package instead.

Is there an official CVE number for this attack?

No. No CVE or CVSS score has been cited for the LiteLLM compromise or for the suspected Claude Code token leak. Because this was a poisoned release rather than a code flaw, CVE-based scanners may not flag it, so check installed versions, lockfiles and container digests directly.

If LiteLLM, an agent framework or an internal model gateway holds your provider and cloud keys, our AI and LLM security testing team can map what an attacker would reach from that host before someone else does.


// get started

Work with CyprusPentest

Tell us about your target and goals. We’ll reply with scope and a fixed-price quote — usually within one business day.

./request_engagement