On March 19, 2026, Trivy, one of the most widely used open-source vulnerability scanners, was turned into an attack vector. A threat group called TeamPCP compromised Aqua Security’s GitHub repository, poisoned 75 out of 76 release tags in trivy-action, and injected malware into CI/CD pipelines around the world. What followed was a multi-stage supply chain attack that reached deep into the npm ecosystem, where it started propagating on its own.
What Happened
The attack unfolded in clearly defined phases. First, the attackers gained access to the aqua-bot service account and used stolen credentials to push direct commits to the Trivy repository. They employed commit impersonation, making commits appear as though they came from legitimate maintainers, which made detection significantly harder.
On March 19 at 17:43 UTC, the attackers pushed manipulated code to the v0.69.4 tag, triggering an automated release pipeline. Within hours, compromised binaries were distributed via GitHub Releases, Docker Hub, GHCR, and ECR. In parallel, 75 of 76 version tags in aquasecurity/trivy-action were force-pushed to point at malicious commits.
The critical insight: anyone referencing trivy-action@v1 or a similar mutable tag in their CI/CD pipeline received compromised code instantly, without any change to their own workflow files.
How Credentials Were Stolen from CI/CD Runners
The injected malware followed a three-stage exfiltration model. In the first step, it scanned GitHub Actions Runner process memory under /proc/<pid>/mem, looking for patterns like {"value":"<secret>","isSecret":true}. This method bypassed the log-masking that GitHub applies to secrets.
Next, the malware swept over 50 known file paths on the runner filesystem: SSH keys, AWS credentials, GCP service account tokens, Azure configurations, Kubernetes kubeconfigs, and even cryptocurrency wallet files.
The collected data was encrypted using a hybrid scheme (AES-256-CBC plus RSA-4096) and exfiltrated to a typosquatted domain: scan.aquasecurtiy.org. As a fallback, the malware created a repository called tpcp-docs within victims’ GitHub organizations.
## Vulnerable pipeline configuration (DO NOT use)
- uses: aquasecurity/trivy-action@v1 # Tag-based = attackable
with:
image-ref: 'myapp:latest'
## Secure alternative: SHA pinning
- uses: aquasecurity/trivy-action@a1c56d356830a78f10e39120e89bb5c383764f46
with:
image-ref: 'myapp:latest'
The difference: a tag like @v1 is a moving target. A force-push changes what it points to without leaving traces. A SHA hash, however, is cryptographically bound to a specific commit. Even with full repository access, the referenced code cannot be swapped out.
CanisterWorm: From CI Runners into the npm Ecosystem
The stolen credentials enabled the next escalation step. Using harvested npm tokens, the attackers initially infected 47 npm packages, which later expanded to 141 malicious artifacts across 66 packages. Among the affected were packages in the @EmilGroup and @opengov scopes.
The malware, which researchers named CanisterWorm, used an unusual command-and-control channel: Internet Computer Protocol (ICP) canisters. A systemd service disguised as PostgreSQL monitoring (pgmon) polled an ICP canister every 50 minutes for new payload URLs.
What made this particularly dangerous: the worm propagated itself. Later variants harvested npm authentication tokens from developer environments and used a deploy.js script to automatically infect every accessible package. A classic worm mechanism, adapted for the package manager ecosystem.
Why This Attack Is Different
Supply chain attacks are not new. SolarWinds (2020), Codecov (2021), ua-parser-js (2021) each compromised individual components. The Trivy attack was the first to combine binary tampering, tag poisoning, persistent backdoors, and a self-propagating worm into a single coordinated campaign.
The real concern is the trust asymmetry at play. Security tools like Trivy run with elevated privileges and rarely face scrutiny themselves. Compromising a vulnerability scanner gives attackers access to credentials, deployment tokens, and environment variables across every project that uses that scanner. A defensive tool becomes an attack vector with maximum blast radius.
Concrete Protective Measures for Teams
The Trivy incident yields actionable recommendations that go beyond the obvious.
SHA pinning for all GitHub Actions is the most important first step. Instead of @v1 or @latest, workflow files should contain the full commit hash. Tools like StepSecurity Harden-Runner automate this process.
Disable postinstall hooks in npm. In CI pipelines, npm install --ignore-scripts should be the default, combined with an explicit allowlist for packages that genuinely need build scripts. This blocks the primary infection vector of CanisterWorm.
## npm install without automatic scripts
npm install --ignore-scripts
## Only explicitly allowed packages may run scripts
npx --package=@pnpm/allow-scripts allow-scripts
Rotate secrets if exposure is suspected. Every team that used Trivy in CI/CD pipelines between March 19 and 23 should rotate all secrets: API keys, deployment tokens, SSH keys, cloud credentials. The official Aqua Security advisory lists affected versions and indicators of compromise.
Runtime monitoring on runners. The creation of unknown systemd services, network connections to ICP endpoints, and reading /proc/*/mem are strong indicators of compromise. Teams serious about CI/CD security should integrate these signals into their monitoring setup.
Enforce dependency pinning with lock files. package-lock.json or pnpm-lock.yaml belong in the repository, version-controlled. Any deviation in CI should break the build, not be silently accepted.
Conclusion
The Trivy attack exposes a structural problem: the tools teams trust with their security are themselves part of the attack surface. Blind trust in third-party actions and package sources is no longer sufficient. SHA pinning, postinstall isolation, and active monitoring of your own supply chain are not optional best practices anymore. They are baseline requirements for secure deployment.
If you want to assess your CI/CD pipelines for supply chain resilience or need support building secure deployment processes, EverBright IT brings hands-on experience from enterprise projects across the DACH region.
Frequently Asked Questions
How did the Trivy attack compromise CI/CD pipelines?
Attackers gained access to the aqua-bot service account and force-pushed malicious commits to 75 of 76 tags in trivy-action. Anyone using mutable tags like @v1 in their workflow received compromised code instantly without changing their own files. This was a multi-stage attack reaching across package managers worldwide.
What is CanisterWorm and how did it spread?
CanisterWorm is a self-propagating malware that harvested npm tokens from CI runners and infected packages in the npm ecosystem. It used Internet Computer Protocol canisters for command and control and automatically spread to accessible packages using stolen tokens, spreading to 141 artifacts across 66 packages.
Why is SHA pinning critical for GitHub Actions security?
SHA pinning uses cryptographically bound commit hashes instead of mutable tags. A tag like @v1 can be force-pushed to point to different code without detection. A SHA hash cannot be changed without breaking the reference, making forced tag poisoning attacks impossible.
How did attackers steal credentials from CI runners?
The malware scanned GitHub Actions runner memory and filesystem for credentials. It looked for secrets in /proc/
What immediate steps should teams take after the Trivy attack?
Use SHA pinning instead of mutable tags for all GitHub Actions. Disable postinstall scripts in npm with npm install —ignore-scripts. Rotate all secrets immediately if your team used Trivy between March 19 and 23. Enable runtime monitoring for unknown systemd services and network connections to suspicious endpoints.