· 10 min read

A Second LiteLLM Security Incident Just Hit 2,500+ Companies. If You Self-Host a Model Router, This Isn't June's Bug.

On August 11, threat intelligence firm CloudSEK disclosed that a compromise of LiteLLM's build pipeline, dating back to March 2026, left more than 2,500 organizations and roughly 434,000 CI/CD pipelines potentially exposed. High-confidence matches in the exposure dataset include AWS, Cisco, Salesforce, Siemens, Nvidia, and X Corp. If you self-host LiteLLM or any model-routing proxy, the number that should stop you isn't 2,500. It's that nobody exploited an application bug to get in.

This is not the June CVE

I covered LiteLLM here in June, when CISA added CVE-2026-42271 to its Known Exploited Vulnerabilities catalog: a command injection bug in LiteLLM's MCP test endpoints, chained with a Starlette host-header bypass, that let attackers hit a live LiteLLM deployment and get unauthenticated remote code execution. That was an application vulnerability. You patched it by upgrading LiteLLM to 1.83.7 and getting the admin surface off the public internet.

This is a different incident, unrelated to that CVE, and it doesn't work the same way. Nobody found a hole in LiteLLM's code and exploited it. Attackers compromised Trivy, the open-source security scanner that LiteLLM's own build pipeline pulls in during CI, and used that foothold to push two poisoned versions of LiteLLM itself to PyPI. Patching LiteLLM promptly in June would have done nothing to stop this, because the malicious code shipped from an official release channel with a legitimate-looking version number. If you only read one of these two posts, that's the sentence to remember: in June the attack surface was LiteLLM's application code, in August it's LiteLLM's supply chain.

What actually happened

According to CloudSEK's report and LiteLLM's own security advisory, the chain started with Aqua Security's Trivy scanner, not LiteLLM. Attackers got hold of a Trivy automation token in late February 2026. Rather than revoking it outright, whoever caught the leak rotated it but didn't fully kill it, and that left roughly a 20-day window where the attacker could force-push malicious commits over Trivy's published version tags. LiteLLM's CI pipeline installed Trivy unpinned, straight from the system package manager, so the poisoned scanner flowed into LiteLLM's own build process without anyone approving a version bump.

That build produced two malicious LiteLLM releases, versions 1.82.7 and 1.82.8, published to PyPI on March 24, 2026. They were live for about 40 minutes before LiteLLM's maintainers worked with PyPI to pull them. Forty minutes doesn't sound like much until you remember what CI/CD pipelines are built to do: pull dependencies automatically, at machine speed, without a human in the loop. The payload itself was nasty in a specific way. It shipped as a .pth file, a mechanism that runs at Python interpreter startup rather than on import, so it executed just from the package being installed, no import litellm required. That sidesteps the --ignore-scripts protection a lot of teams rely on. Once running, the malware (Google's threat intel team tracks it as SANDCLOCK) swept SSH keys, AWS/GCP/Azure credentials read straight from instance metadata, Kubernetes tokens, .env files, and LLM API keys, encrypted the haul, and shipped it out. Where exfiltration failed, it reportedly created a public repository inside the victim's own GitHub account and dropped the stolen data there as a release asset.

The threat actor group behind it, tracked as TeamPCP, isn't a one-off. Security researchers quoted in coverage of the incident say the same group hit Microsoft's durabletask-python package twice this year using a similar pattern: compromise a trusted build tool, ride it into a popular package, harvest whatever the CI runner can reach.

The scale, and what the numbers actually mean

CloudSEK's headline figures, 2,500+ organizations and roughly 434,000 CI/CD pipelines, come from reconstructing exposure across the incident, and the firm is explicit that a listing in that dataset is not proof of a successful breach. Its own methodology table distinguishes "exposed" (linked to an affected artifact, needs validation) from "probable compromise" (evidence of execution or credential access) from "confirmed compromise" (verified malicious use). The organizations named as high-confidence matches, which reporting lists as including AWS, Samsung, Cisco, Salesforce, Siemens, S&P Global, ServiceNow, Deloitte, Volkswagen, X Corp, and Nvidia among others, sit in that first bucket by CloudSEK's own framing: a strong match on domain, repository, or credential evidence, not a confirmed intrusion. Worth being precise about that distinction, because "flagged as a potential match" and "breached" are different claims, and the coverage of this story hasn't always kept them separate.

The FBI added its own weight to this in July, issuing a FLASH advisory (FLASH-20260702-01) warning that TeamPCP-linked actors are likely to keep using credentials harvested in incidents like this one well after the fact. A stolen AWS key doesn't expire when the malicious package gets pulled from PyPI. It expires when someone rotates it, and that's the part a 40-minute exposure window doesn't fix.

What a solo operator should actually check

If you're running LiteLLM, or Kong, or any self-hosted model-routing proxy, the June lesson was patch cadence: watch the CVE feed, upgrade fast. This incident asks a different question, one most solo setups have never looked at: what's inside your build pipeline, and did you pin it?

Concretely: check whether your CI installs security scanners, linters, or other build tooling unpinned (apt install trivy rather than a hash-pinned version), because that's exactly the door this attack walked through. Pin GitHub Actions to commit SHAs instead of mutable tags like @v1, since tag force-pushes are precisely how the Trivy compromise spread. If you maintain a Software Bill of Materials, or even just a lockfile you actually check, you can answer "was 1.82.7 or 1.82.8 ever in my stack" in minutes instead of hours. And if the answer is yes, or you can't rule it out, rotate everything that CI runner could reach, not just your LiteLLM or model-provider keys. Cloud credentials, SSH keys, and package-publishing tokens were all in scope here.

What I'd actually do

I don't audit my build tooling's provenance the way I audit my application dependencies, and this incident is the reason I'm changing that this week. I check pip list --outdated and read release notes before bumping LiteLLM, sure, but I've never once checked whether the GitHub Action I use for container scanning is pinned to a SHA or a mutable tag. Most solo stacks are the same: heavy scrutiny on the app dependency, zero scrutiny on the thing that builds it. So the concrete move is to go through my CI config this week and replace every uses: some-action@v1 with a commit hash, and to stop installing scanners or linters via the OS package manager without pinning a version.

Here's the honest counter-take: for a genuinely solo operator running a small self-hosted stack, the actual blast radius of this specific incident is probably low. You're not Cisco or Volkswagen; your CI runner doesn't hold thousands of secrets across a sprawling org. The bigger the company, the bigger the number of pipelines and credentials a single poisoned dependency can reach, which is exactly why the named victims skew toward large enterprises. If your LiteLLM install never touched 1.82.7 or 1.82.8 in that 40-minute window, you were never in this specific blast radius. But the pattern generalizes past this one incident: your dependencies' dependencies are also your attack surface, and "I patched the last CVE" was never going to catch a poisoned release published from an official channel with a version number nobody thought to question.

Author

Sources

Stay in the Loop

Get new posts delivered to your inbox. No spam, unsubscribe anytime.

Newsletter coming soon. Set PUBLIC_CONVERTKIT_FORM_ID in .env to activate.

Related Posts