Threat Intelligence
The Security Scanner That Became the Weapon
March 24, 10:39 UTC.
The first poisoned LiteLLM package landed on PyPI two minutes earlier, and on some CI runner somewhere, the credential harvest had already started. Nobody outside the attacker noticed for hours. That is the uncomfortable part of this story: the tool most organizations run to find vulnerabilities was the tool used to create them.
I have tracked supply chain incidents for years, and this one is different in a way that matters for defenders. The attack did not begin with LiteLLM at all. It began with a scanner named Trivy, made by Aqua Security, which a financially motivated group calling itself TeamPCP hijacked and turned against the software industry. The result is one of the largest reconstructed credential exposures of the past year: CloudSEK and Hudson Rock independently estimate 2,488 to 2,500+ organizations and up to 434,000 CI/CD pipelines touched within a single 40-minute to 5-hour window.
The Chain, Not the Package
Understanding this incident means understanding the cascade. In late February, an actor exploited a misconfigured `pull_request_target` workflow in Trivy’s own CI to steal a GitHub personal access token. Aqua disclosed the breach, but the rotation was not atomic, leaving the attacker roughly 20 days of residual access. On 19 March, TeamPCP used the still-valid token to force-push credential-stealing code onto 76 of 77 trivy-action tags and all seven setup-trivy tags and published malicious Trivy v0.69.4. Docker Hub images v0.69.5 and v0.69.6 followed three days later. The poisoning is tracked as CVE-2026-33634, CVSS 9.4 critical, and sits on CISA’s known-exploited list.
LiteLLM was collateral damage. Its build pipeline installed Trivy unpinned from an apt repository, with no version pinning and no checksum verification. The poisoned scanner auto installed, dumped the CI runner’s process memory, swept filesystem paths for credentials, and drained the token LiteLLM used to publish to PyPI. Then TeamPCP published `litellm==1.82.7` and `1.82.8` directly to PyPI on March 24. The first package fires its payload on `import litellm.proxy`; the second ships a `.pth` file that executes on every Python interpreter startup, no import needed. A note on versions, because it matters for detection: the malicious Trivy versions are v0.69.4 through v0.69.6, and the malicious LiteLLM versions are 1.82.7 and 1.82.8. Conflating them will trip up your search queries.
What the Payload Took
The payload is a three-stage design built for scale, not stealth. Stage one harvests credentials: cloud keys across AWS, GCP, and Azure including IMDS and AWS Secrets Manager, GitHub and GitLab PATs, SSH keys, Kubernetes tokens, npm and PyPI publishing tokens, database passwords, crypto wallets, and AI provider API keys. For an AI gateway like LiteLLM, that last class is the distinctive haul: every LLM provider key configured in the gateway. Organizations treat those as internal, but attackers can resell them or burn them at cost.
Stage two encrypts the loot with AES-256-CBC, wraps the session key with a hardcoded RSA-4096 key, packs it as `tpcp.tar.gz`, and POSTs it to a typosquatted domain, `models.litellm.cloud`. Stage three persists: a systemd service polls a second C2 domain every 50 minutes for a second-stage payload; and on Kubernetes, it attempts privileged pods in kube-system. Removing the package does not remove the backdoor. I have seen incident responders miss this, and the persistence survives uninstall.
The Numbers Need a Caveat
Here is where I must slow you down because the headlines are running ahead of the evidence. The 2,500+ organization figure is reconstructed exposure, not a confirmed breach count. The two firms derive their numbers from the same leaked credential corpus, and their counts measure different populations: CloudSEK counts pipelines in affected organizations, an upper-bound estimate, while Hudson Rock counted 118,829 individual runner dumps in a 153 GB archive. No named organization has publicly confirmed a breach. The SiriusXM entry turned out to be a subsidiary. Treat the figure as a floor on exposure, not a victim list.
The risk is nonetheless live. The corpus is being worked, with SANS reporting TeamPCP cooperating with ransomware affiliates, and the FBI warning that stolen credentials from this campaign are likely to be weaponized long after the initial compromise. Long-lived classes, static cloud keys, publishing tokens, and AI provider keys hold value months later. Rotation is not waiting for a confirmed breach.
What You Do About It
Treat every secret that a pipeline running Trivy, KICS, or LiteLLM between March 19 and 24 as if it could have read as compromised, and rotate it. This includes secrets in process memory, job-injected variables, `.env` files, and IMDS-retrievable tokens. Delete `litellm_init.pth`, stop and disable the `sysmon.service`, clear `/tmp/pglog` and `/tmp/.pg_state`, and remove any `node-setup-*` pods. Rebuild affected runners from pinned images. Then do the work that prevents the next one: pin every GitHub Action to a full commit SHA, pin scanner and package versions with checksum verification, stop fetching “latest” from apt or any repo, move secrets into a vault with short-lived scoped credentials, and adopt keyless OIDC Trusted Publishing with SLSA provenance, the fix LiteLLM itself shipped in PR #28025.
Detection content exists. SigmaHQ merged two rules for this campaign in PR #5923, one for process creation and one for file events, and a LimaCharlie hunt covers the `.pth` execution and RSA key-wrap behaviour. If your SOC has not deployed them, this is the week.
Analyst Assessment
The exposure is real at the thousands-of-pipelines scale, the breach count is unknown and likely overstated as currently publicized, and the credentials retain open-ended value, so rotation and artifact removal are the only safe postures and neither depends on the breach question resolving.