TL;DR
- Supply-Chain Breach: Attackers hijacked 75 of 76 GitHub Actions tags for Aqua Security’s Trivy scanner, distributing credential-stealing malware through the trusted security tool.
- Second Compromise: The attack stemmed from incomplete containment of an earlier March 1 breach, where non-atomic secret rotation left attackers with continued repository access.
- npm Worm: A self-propagating worm called CanisterWorm compromised 47 npm packages using stolen tokens, spreading malicious code across the JavaScript ecosystem.
- Recommended Action: Organizations should pin GitHub Actions to commit SHA hashes instead of version tags and rotate any credentials that transited affected pipelines.
Aqua Security revealed on March 21 that attackers hijacked 75 of 76 GitHub Actions tags for its Trivy vulnerability scanner, distributing credential-stealing malware through the widely used security tool for the second time in a single month. Malicious code rode alongside legitimate scans, targeting SSH keys, cloud tokens, and API secrets in CI/CD pipelines.
More than 10,000 GitHub workflow files rely on trivy-action, meaning any pipeline that pulled affected versions during the attack window may have had sensitive credentials exfiltrated. Beyond Trivy users, a self-propagating npm worm compromised 47 packages, extending the blast radius into the broader JavaScript ecosystem. Aqua Security disclosed in a GitHub Discussion that the incident stemmed from incomplete containment of an earlier March 1 breach involving a hackerbot-claw bot.
How Attackers Hijacked Trivy’s Build Pipeline
On March 1, a hackerbot-claw bot exploited a pull_request_target workflow to exfiltrate repository secrets from Trivy’s GitHub environment. Aqua Security rotated credentials after that first breach, but gaps in the rotation process left attackers with continued write access to the repository, setting the stage for the larger second compromise three weeks later.
Armed with that access, attackers swapped the entrypoint.sh in Trivy’s GitHub Actions with a 204-line script that prepended credential-stealing code before the legitimate scanner. Lines 4 through 105 contained the infostealer payload, while lines 106 through 204 ran Trivy as normal, making the compromise difficult to detect during routine scans. Security researcher Paul McCarty was the first to warn publicly that Trivy version 0.69.4 had been backdoored, with malicious container images and GitHub releases published to users.
According to Socket security researcher Philipp Burckhardt, attackers force-pushed 75 out of 76 tags in the trivy-action repository, turning trusted version references into infostealer distribution points. Commit metadata including author names, emails, and timestamps was spoofed to match legitimate patterns, but a key detection indicator remained: original commits carried GPG signatures from GitHub, while attacker commits lacked any signature. Socket generated 182 threat feed entries tied to malicious GitHub Actions associated with this campaign.
Unlike the March 2025 tj-actions/changed-file incident, where malicious code replaced the action entirely, TeamPCP preserved normal scan functionality to avoid triggering CI/CD failures. Detection now requires cryptographic verification of commit signatures rather than behavioral monitoring alone, a significant shift that many organizations have not yet implemented in their CI/CD security controls.
For defenders, traditional CI/CD monitoring, which watches for build failures or unexpected output, can no longer catch supply-chain compromises that deliberately maintain normal behavior. Organizations relying on Trivy or similar open-source security tools face a paradox: the very scanners meant to protect their pipelines can become the attack vector, and only cryptographic provenance checks can distinguish legitimate releases from poisoned ones.
Once inside a pipeline, the malicious script scanned memory regions of the GitHub Actions Runner. Worker process for JSON strings containing name, value, and isSecret fields to locate authentication secrets. It also harvested environment variables containing cloud credentials, SSH keys, and cryptocurrency wallet files. Collected data was encrypted with AES-256-CBC, wrapped with RSA-4096, and exfiltrated to a typosquatted domain at scan.aquasecurtiy[.]org.
If that exfiltration path failed, the malware created a public repository named tpcp-docs within the victim’s GitHub account as a fallback data dump. Aqua Security pulled the malicious v0.69.4 release after it was live for approximately three hours, though compromised GitHub Actions tags remained accessible for up to 12 hours. Because GitHub Actions tags are mutable references that can be force-pushed at any time, pinning workflows to version tags rather than immutable commit hashes creates a structural vulnerability that a single compromised credential can exploit at scale.
CanisterWorm Spreads to npm Ecosystem
Beyond GitHub Actions, TeamPCP launched a follow-up attack targeting the npm registry, expanding the breach from CI/CD pipelines into the JavaScript package ecosystem. Aikido researchers identified a self-propagating npm worm called CanisterWorm that compromised 47 packages by stealing npm tokens, enumerating all publishable packages under a victim’s account, and automatically publishing malicious versions.
CanisterWorm installs a persistent backdoor via a systemd user service, then spreads to every package under the compromised account. Its novel command-and-control mechanism uses Internet Computer (ICP) canisters as a dead-drop resolver, marking the first known use of decentralized blockchain infrastructure for C2 in a supply-chain campaign. Leveraging ICP’s censorship-resistant storage made takedown efforts materially harder than with traditional domain-based C2 infrastructure.
“Self-propagating worm. deploy.js takes npm tokens, resolves usernames, enumerates all publishable packages, bumps patch versions, and publishes the payload across the entire scope. 28 packages in under 60 seconds.”
Aikido, Security Research Firm (via Aikido)
Automated publishing at that speed meant a single compromised npm token could poison dozens of downstream projects within minutes, cascading across dependency trees before maintainers received any notification. Combining GitHub Actions tag hijacking with an automated npm worm creates a compounding threat: development teams must now audit both CI/CD configuration and dependency provenance simultaneously to contain their exposure.
Incomplete Containment Enabled the Second Attack
Aqua Security acknowledged that its response to the March 1 incident failed to fully neutralize the threat. Secret rotation was not performed atomically, allowing attackers to monitor the rotation process and capture refreshed credentials before the changeover completed. Attackers exploited that window to publish malicious versions of trivy, trivy-action, and setup-trivy before the new credentials could be locked down.
“We rotated secrets and tokens, but the process wasn’t atomic, and attackers may have been privy to refreshed tokens. We are now taking a more restrictive approach and locking down all automated actions and any token in order to thoroughly eliminate the problem.”
Itay Shakury, VP of Open Source at Aqua Security (via Aqua Security)
Non-atomic credential rotation illustrates a broader gap in incident response practices. When attackers already have access to the rotation pipeline itself, issuing new credentials without first revoking old ones effectively gives adversaries two valid token sets instead of zero, undermining the entire remediation effort.
Compounding the containment failure, attackers deleted the earlier incident disclosure from GitHub Discussions, making it harder for the community to assess ongoing risk. Prior incidents have demonstrated similar systemic weaknesses: in August 2024, a separate GitHub Actions security vulnerability exposed CI/CD secrets in projects maintained by Google, Microsoft, and AWS, while a March 2025 compromise of the tj-actions/changed-files action followed the same pattern of stolen credentials injecting malicious code into a trusted CI/CD component.
Security researchers at Wiz linked the attack to TeamPCP, a cloud-native threat group also tracked as DeadCatx3, PCPcat, and ShellForce. Wiz identified the group through a self-identification string embedded in one of the infostealer payloads. Credential targets found in the payload, including cloud provider tokens, container registry access keys, and API secrets, are consistent with TeamPCP’s broader theft-and-monetization profile, which has historically focused on stealing cloud compute resources for cryptocurrency mining and reselling compromised infrastructure access.
Aqua Security urged affected users to “treat all pipeline secrets as compromised and rotate immediately.” Organizations that ran any version of trivy-action, setup-trivy, or Trivy v0.69.4 during the attack window should audit their CI/CD logs for unexpected network connections to scan.aquasecurtiy[.]org and check whether any tpcp-docs repositories were created under their GitHub accounts. With three major tag-hijacking incidents in 12 months, Wiz security researcher Rami McCarthy recommended that organizations “pin GitHub Actions to full SHA hashes, not version tags.”
For the thousands of development teams that still reference actions by mutable tags, migrating to hash-based pinning and revoking any npm tokens exposed during the CanisterWorm campaign are now urgent steps. Any credentials that transited a compromised pipeline remain valid until explicitly rotated, leaving cloud infrastructure, container registries, and source code repositories exposed to ongoing unauthorized access.

