Trivy Supply Chain Attack Triggers Self-Spreading CanisterWorm Across 47 npm Packages
Summary:
On March 19 and March 20, 2026, a threat actor known as TeamPCP executed a highly impactful, cross-ecosystem supply chain attack. The campaign began with the compromise of Aqua Security's Trivy vulnerability scanner and quickly expanded into a self-propagating worm, known as CanisterWorm, across the npm registry. By exploiting incomplete containment from a previous incident, TeamPCP injected credential-stealing malware into official Trivy releases and GitHub Actions, which was then used to harvest publish tokens. These stolen tokens enabled a fast-moving npm attack that infected dozens of packages with a persistent Python backdoor. To maximize the impact and evade detection, TeamPCP heavily utilized social engineering and masquerading tactics throughout both phases of the attack. During the npm registry compromise, the automated worm was specifically engineered to preserve the original README files of targeted packages while incrementally bumping the patch version numbers, such as changing version 1.54.0 to 1.54.1. This campaign is strategically significant due to its rapid operational tempo, its evasion techniques targeting CI/CD environments, its use of decentralized command and control infrastructure, and its successful pivoting from GitHub Actions directly into a massive open-source registry.
Security Officer Comments:
The threat actor initiated the attack by making malicious commits to actions/checkout (spoofing the user rauchg) and aquasecurity/trivy (spoofing the user DmitriyLewen). This triggered the malicious v0.69.4 release. The attacker also compromised the aqua-bot service account, pushing malicious workflows to tfsec, traceeshark, trivy-action, and setup-trivy. The malware exfiltrated secrets, including npm publish tokens, which were then fed into an automated script (deploy.js). This standalone worm tool authenticated with the npm registry, enumerated publishable packages, bumped patch versions, and published a malicious three-stage payload across entire scopes, affecting 28 packages in the @EmilGroup scope and 16 packages in the @opengov scope, among others. By preserving the original README files, the threat actor drastically increases the likelihood that the malicious updates appear as routine, benign patch releases to automated systems.
This campaign relies on two primary malware families designed to target distinct stages of the CI/CD pipeline. The first, dubbed the TeamPCP Cloud Stealer, is a payload injected directly into the entrypoint[.]sh and action.yaml files of compromised GitHub Actions. Once triggered, this malware scrapes the Runner.Worker process memory for secrets and sweeps the local filesystem for sensitive data, including SSH keys, cloud credentials, and Kubernetes tokens. The harvested data is then encrypted using AES-256-CBC and RSA-4096 hybrid encryption, bundled into a tarball, and exfiltrated. Additionally, the malicious Trivy binary evaluates the GITHUB_ACTIONS environment variable. If it determines it is running on a developer's workstation by confirming GITHUB_ACTIONS != "true", it establishes persistence by dropping a Python script (~/.config/systemd/user/sysmon.py) configured as a systemd service.
The second malware family, CanisterWorm, is a three-stage npm payload that begins with a Node.js postinstall loader wrapped in a try/catch block to ensure it fails silently. This loader decodes and installs a persistent Python backdoor using user-level systemd services, requiring no root access. To evade sandbox detection, the Python backdoor sleeps for five minutes before initiating network activity. Once active, it polls a decentralized Internet Computer Protocol (ICP) canister every 50 minutes. This canister functions as a C2 dead-drop, providing a dynamic URL from which the backdoor downloads its final executable payload to /tmp/pglog.
Suggested Corrections:
Actionable Suggested Correctionss
https://thehackernews.com/2026/03/trivy-supply-chain-attack-triggers-self.html
https://www.aikido.dev/blog/teampcp-deploys-worm-npm-trivy-compromise
https://www.wiz.io/blog/trivy-compromised-teampcp-supply-chain-attack
On March 19 and March 20, 2026, a threat actor known as TeamPCP executed a highly impactful, cross-ecosystem supply chain attack. The campaign began with the compromise of Aqua Security's Trivy vulnerability scanner and quickly expanded into a self-propagating worm, known as CanisterWorm, across the npm registry. By exploiting incomplete containment from a previous incident, TeamPCP injected credential-stealing malware into official Trivy releases and GitHub Actions, which was then used to harvest publish tokens. These stolen tokens enabled a fast-moving npm attack that infected dozens of packages with a persistent Python backdoor. To maximize the impact and evade detection, TeamPCP heavily utilized social engineering and masquerading tactics throughout both phases of the attack. During the npm registry compromise, the automated worm was specifically engineered to preserve the original README files of targeted packages while incrementally bumping the patch version numbers, such as changing version 1.54.0 to 1.54.1. This campaign is strategically significant due to its rapid operational tempo, its evasion techniques targeting CI/CD environments, its use of decentralized command and control infrastructure, and its successful pivoting from GitHub Actions directly into a massive open-source registry.
Security Officer Comments:
The threat actor initiated the attack by making malicious commits to actions/checkout (spoofing the user rauchg) and aquasecurity/trivy (spoofing the user DmitriyLewen). This triggered the malicious v0.69.4 release. The attacker also compromised the aqua-bot service account, pushing malicious workflows to tfsec, traceeshark, trivy-action, and setup-trivy. The malware exfiltrated secrets, including npm publish tokens, which were then fed into an automated script (deploy.js). This standalone worm tool authenticated with the npm registry, enumerated publishable packages, bumped patch versions, and published a malicious three-stage payload across entire scopes, affecting 28 packages in the @EmilGroup scope and 16 packages in the @opengov scope, among others. By preserving the original README files, the threat actor drastically increases the likelihood that the malicious updates appear as routine, benign patch releases to automated systems.
This campaign relies on two primary malware families designed to target distinct stages of the CI/CD pipeline. The first, dubbed the TeamPCP Cloud Stealer, is a payload injected directly into the entrypoint[.]sh and action.yaml files of compromised GitHub Actions. Once triggered, this malware scrapes the Runner.Worker process memory for secrets and sweeps the local filesystem for sensitive data, including SSH keys, cloud credentials, and Kubernetes tokens. The harvested data is then encrypted using AES-256-CBC and RSA-4096 hybrid encryption, bundled into a tarball, and exfiltrated. Additionally, the malicious Trivy binary evaluates the GITHUB_ACTIONS environment variable. If it determines it is running on a developer's workstation by confirming GITHUB_ACTIONS != "true", it establishes persistence by dropping a Python script (~/.config/systemd/user/sysmon.py) configured as a systemd service.
The second malware family, CanisterWorm, is a three-stage npm payload that begins with a Node.js postinstall loader wrapped in a try/catch block to ensure it fails silently. This loader decodes and installs a persistent Python backdoor using user-level systemd services, requiring no root access. To evade sandbox detection, the Python backdoor sleeps for five minutes before initiating network activity. Once active, it polls a decentralized Internet Computer Protocol (ICP) canister every 50 minutes. This canister functions as a C2 dead-drop, providing a dynamic URL from which the backdoor downloads its final executable payload to /tmp/pglog.
Suggested Corrections:
Actionable Suggested Correctionss
- Audit Trivy Deployments: Identify and immediately remove any artifacts, container images, or binaries associated with Trivy versions 0.69.4, 0.69.5, and 0.69.6.
- Review GitHub Actions: Check workflow run logs from March 19 and March 20 for signs of compromise, specifically targeting the "Run Trivy" step of trivy-action and the "Setup environment" step of setup-trivy.
- Block Malicious Infrastructure: Implement network blocking for the identified C2 domains
- Hunt for Fallback Mechanisms: Search your organization's GitHub environments for newly created repositories named tpcp-docs, which indicate successful exfiltration.
- Scan Developer Workstations: Hunt for the presence of the disguised PostgreSQL artifacts (pgmon, pglog, .pg_state) and the malicious systemd services in user directories (~/.config/systemd/user/).
- Pin GitHub Actions: Always pin GitHub Actions to full SHA hashes rather than version tags to prevent tag manipulation attacks.
- Enhance Token Security: Revoke and rotate all npm publish tokens, GitHub Action secrets, and cloud credentials that may have been exposed during CI/CD runs.
- Monitor CI/CD Environments: Implement runtime monitoring on developer machines and CI/CD runners to detect anomalous memory scraping, unauthorized systemd service creation, and unexpected outbound connections to decentralized platforms like ICP.
https://thehackernews.com/2026/03/trivy-supply-chain-attack-triggers-self.html
https://www.aikido.dev/blog/teampcp-deploys-worm-npm-trivy-compromise
https://www.wiz.io/blog/trivy-compromised-teampcp-supply-chain-attack