Your Security Scanner Is Now the Attack: The Trivy Supply Chain Compromise
title: "Your Security Scanner Is Now the Attack: The Trivy Supply Chain Compromise"
tags: ["supply chain", "CI/CD", "Trivy", "LiteLLM", "TeamPCP", "credential theft"]
If you use Trivy in your CI/CD pipelines, stop what you're doing. Not because Trivy is bad software — because attackers got inside it, and your pipelines may have already run the malicious version.
What happened
On March 25, Aqua Security disclosed that their open-source Trivy vulnerability scanner had been hit by a supply chain attack. The method was precise: threat actors stole credentials, waited, then force-pushed malicious commits directly onto existing version tags in the `aquasecurity/trivy-action` and `setup-trivy` GitHub repositories.
Version `trivy-action v0.69.4` was the poisoned release. Pipelines that referenced this tag by version string — not by commit hash — silently pulled and executed malicious code before Trivy's legitimate scan ever ran.
What did it steal? Everything your pipeline had access to: AWS credentials, GCP service account keys, Azure tokens, SSH keys, Kubernetes cluster tokens, Docker config files. The payload ran first, exfiltrated, then handed off to the legitimate scanner so nothing looked wrong in your pipeline logs.
The initial breach happened in February. Aqua did a partial credential rotation on March 1. It wasn't enough — the attacker still had access, reactivated, and the malicious commits went in.
The downstream blast radius: LiteLLM
This didn't stop at Trivy. The same campaign — attributed to threat actor group TeamPCP — used the compromised Trivy as a stepping stone into LiteLLM, a Python package that sits in front of 100+ LLM providers and had roughly 95 million monthly downloads.
LiteLLM's CI/CD scripts pulled Trivy without version pinning. The compromised Trivy binary had access to LiteLLM's PyPI publishing token. TeamPCP used it.
Versions 1.82.7 and 1.82.8 were malicious packages published directly to PyPI. The attack window was approximately 6.5 hours on March 24 before the packages were pulled.
These versions deployed a `.pth` file — `litellm_init.pth` — into Python's site-packages directory. This mechanism triggers on *every Python interpreter startup*, not just when LiteLLM is explicitly called. Double-base64-encoded payload, running silently, harvesting credentials in under 2 seconds.
On Kubernetes environments: the malware created privileged pods (`node-setup-{node_name}`) in the `kube-system` namespace with `hostPID`, `hostNetwork`, and full host filesystem access. Full cluster takeover.
The SHA pinning problem
You might think: "We pin by SHA, we're fine." CybrPulse tracked additional analysis from security researchers this week showing this assumption has a gap.
GitHub's architecture allows commit SHAs from orphaned forks to remain resolvable. An attacker can pin malicious commits that GitHub still resolves by hash, bypassing the assumption that a pinned SHA guarantees you're pointing at upstream's branch history. The Trivy attack combined this with a typosquatted C2 server and a compromised maintainer account — layers designed to survive surface-level defenses.
What TeamPCP is running
This is the same group behind CanisterWorm, a self-propagating npm supply chain worm CybrPulse also tracked this week. CanisterWorm steals npm publisher tokens via malicious postinstall hooks, then uses those tokens to backdoor the victim's *entire package portfolio* — not just one package. It uses Internet Computer Protocol (ICP) blockchain endpoints for C2, which makes traditional infrastructure takedowns useless.
The pattern is consistent: compromise a trusted security or DevOps tool, weaponize CI/CD credential access, pivot to downstream ecosystems, use decentralized C2 to maintain resilience.
What you need to do right now
If you use Trivy:
- Pin to safe versions: `trivy-action v0.35.0` or `setup-trivy v0.2.6`
- Do not use `v0.69.4` under any circumstances
- Rotate all secrets your pipelines had access to during the exposure window
- Block these C2 addresses: `45.148.10.212`, `scan.aquasecurtiy[.]org`, `tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io`
If you use LiteLLM:
- Check installed versions immediately — 1.82.7 and 1.82.8 are malicious
- Treat any host that ran these versions as fully compromised
- Rotate all LLM API keys, cloud credentials, SSH keys, and Kubernetes tokens on affected hosts
- Check for the `litellm_init.pth` file in your Python site-packages — it survives `pip uninstall`
- Check `kube-system` for unexpected `node-setup-*` pods
For your CI/CD posture broadly:
- Stop referencing GitHub Actions by version tags — use full commit SHAs
- Apply that same discipline to your scan runner scripts that pull external binaries
- Audit any pipeline that runs with cloud credentials and verify what it's actually executing
The bigger problem
Your security tooling is now a high-value target. Attackers have figured out that the scanner running in your pipeline has privileged access to everything your pipeline touches — and it runs automatically, on every commit, with no human review.
A compromised vulnerability scanner doesn't just fail to catch your bugs. It becomes the bug. The DevSecOps trust model depends on those tools being clean. When they're not, you get credential exfiltration at pipeline speed, across every repo in your organization.
The incomplete credential rotation after February's initial breach is what enabled March's damage. When you rotate after a compromise, rotate everything. Assume the attacker has access until proven otherwise.