TeamPCP’s Five-Day Siege: How One Stolen Token Cascaded Across GitHub Actions, Checkmarx, VS Code Extensions, and npm

Evolution of Team PCPC Attack: devsecops, ASPM, application security, vulnerability management, supply chain attack, GitHub Actions security, CI/CD compromise, reachability analysis, attack surface management, exposure management, TeamPCP, Trivy compromise, Checkmarx KICS, CanisterWorm, npm malware, ICP blockchain C2

Executive Summary

Between March 19 threat actor TeamPCP compromised Aqua Security’s and March 23 2026 (disclosed by Paul McCarty). The threat actor TeamPCP executed the most consequential CI/CD supply chain attack documented to date. Starting from a single incompletely-rotated GitHub personal access token, the campaign cascaded across two major open-source security vendors (Aqua Security and Checkmarx), four GitHub Actions repositories, two OpenVSX extensions, container registries (Docker Hub, GHCR, ECR), and over 66 npm packages.

We did cover the attacks in previous articles, as the situation is evolving. The first article covered the initial attack, a second one was a deep dive into the Trivy compromise,  and this one covers more techniques and the new Kicks attack.

The attacker force-pushed 110+ version tags across aquasecurity/trivy-action, aquasecurity/setup-trivy, Checkmarx/kics-github-action, and Checkmarx/ast-github-action, replacing them with malicious commits containing a three-stage credential stealer self-identified as the “TeamPCP Cloud stealer.” The stealer dumps Runner.Worker process memory, sweeps 50+ credential paths on self-hosted runners, encrypts harvested data with AES-256-CBC and RSA-4096, and exfiltrates via vendor-specific typosquat domains designed to blend into CI/CD log output.

Stolen npm tokens then fuelled CanisterWorm, the first publicly documented npm malware to use an Internet Computer Protocol (ICP) blockchain canister as a command-and-control dead-drop, making conventional domain takedown impossible. A destructive variant specifically targeting Iranian Kubernetes clusters was also detected.

The campaign had no CVE, no CVSS score, and no NVD entry. Traditional scanner-based vulnerability management workflows would not have caught it.

TL;DR for Engineering Teams

What it is: Multi-vendor supply chain compromise of Trivy and Checkmarx GitHub Actions, OpenVSX extensions, container images, and 66+ npm packages, injecting a three-stage credential stealer attributed to TeamPCP. No CVE assigned for the March 2026 wave.

Where it bites: Any CI/CD pipeline referencing aquasecurity/trivy-action (75 of 76 tags), aquasecurity/setup-trivy (7 tags), Checkmarx/kics-github-action (all 35 tags), Checkmarx/ast-github-action (confirmed: v2.3.28), Trivy binary v0.69.4–0.69.6, OpenVSX extensions ast-results v2.53.0 and cx-dev-assist v1.7.0, or any CanisterWorm-affected npm package.

Why it matters: Payload executes before the legitimate scan, so pipelines appear normal. The stealer dumps Runner.Worker process memory, harvests SSH keys, cloud credentials, K8s tokens, crypto wallets, and npm tokens. Stolen npm tokens enabled a self-propagating worm using blockchain-based C2 that cannot be taken down via conventional means. 10,000+ workflows affected across both vendors.

Patch status: Trivy: malicious artifacts removed, tags restored with v-prefix, immutable releases enabled. Safe versions: trivy v0.69.3, trivy-action v0.35.0 (SHA 57a97c7e), setup-trivy v0.2.6. Checkmarx: kics-github-action repository reinstated and declared resolved. OpenVSX: extensions reported for removal.

Immediate action: Pin all affected actions to verified SHA commits. Rotate every secret accessible to CI runners during the exposure windows (Trivy: March 19 17:43–March 20 05:40 UTC; KICS: March 23 12:58–16:50 UTC). Block scan.aquasecurtiy[.]org, checkmarx[.]zone, 45.148.10.212, 83.142.209.11. Search GitHub orgs for tpcp-docs or docs-tpcp repositories. Audit npm packages for CanisterWorm IOCs.

Vulnerability Overview

FieldValue
VendorsAqua Security, Checkmarx
ProductsTrivy, trivy-action, setup-trivy, KICS, kics-github-action, ast-github-action, ast-results (OpenVSX), cx-dev-assist (OpenVSX)
Vulnerability TypeSupply chain compromise / credential theft / self-propagating worm
CWECWE-829 (Inclusion of Functionality from Untrusted Control Sphere)
CVENo CVE assigned for March 2026 wave; GHSA-69fq-xp46-6×23 covers Trivy ecosystem
Attack VectorNetwork (CI/CD pipeline execution, IDE extension activation)
Active ExploitationConfirmed — multi-vendor, multi-ecosystem
AttributionTeamPCP (also tracked as DeadCatx3, PCPcat, ShellForce, CipherForce)
Trivy Exposure Window~12 hours (March 19 17:43 UTC to March 20 ~05:40 UTC)
KICS Exposure Window~4 hours (March 23 12:58 UTC to ~16:50 UTC)

Technical Anatomy

Phase 1: Initial Access via GitHub Actions Misconfiguration (Late February 2026)

The campaign’s origins trace to late February 2026 when the hackerbot-claw account (created February 20) began scanning public repositories for exploitable GitHub Actions workflows. The account’s approach was methodical: it targeted repositories with pull_request_target triggers that checked out attacker-controlled code, a well-documented class of misconfiguration known as a “PWN request.”

The attacker exploited multiple techniques across different targets. Against one Microsoft repository, the payload was embedded in the Git branch name itself, using shell expansion ($(…)) to achieve command injection when the branch name was echoed in a workflow step. Against a Datadog repository, the same shell expansion was delivered via a malicious markdown filename that was evaluated during a file-listing step. Against a repository running a Claude-based AI code review bot, the attacker attempted prompt injection to coerce the model into executing arbitrary code. Claude detected and refused both attempts, but the non-deterministic nature of LLM evaluation means repeated attempts could eventually succeed.

The attack that yielded the most impact targeted Aqua Security’s Trivy repository. The hackerbot-claw account forked the Trivy repo and opened a pull request that looked legitimate but included a curl command piped to bash, which ran within the GitHub Action runner’s context. This extracted a GitHub personal access token (PAT) bound to the entire aquasecurity GitHub organization, granting write access to all 33+ repositories.

With org-wide access, the attacker immediately defaced the Trivy repository README, deleted all releases, renamed the repo, and pushed a malicious VS Code extension to OpenVSX. Aqua Security disclosed the breach on March 1 and began rotating credentials. The rotation was not atomic. As tokens were being cycled, the attacker captured refreshed credentials before the old access was fully revoked, setting the stage for the March 19 attack.

Phase 2: The February VS Code Extension Attack — Weaponising Local Coding Agents

An overlooked element of the February breach was the malicious VS Code extension pushed to OpenVSX, which contained a payload specifically designed to exploit local AI coding assistants. The extension scanned for five installed coding agents (Claude Code, Google Gemini, GitHub Copilot, Codex, and others) and attempted to invoke them in their most permissive modes: –dangerously-skip-permissions for Claude, –yolo for Gemini/Copilot, and –ask-for-approval never for Codex.

The embedded prompt, over 2,000 words long, impersonated a forensic analyst and instructed the agent to scan the local system for credentials, financial data, cloud tokens, and security configurations. The initial version attempted multi-channel exfiltration (email, encrypted portals, written reports). A second iteration specifically directed the agent to use the GitHub CLI or API to upload findings to a public repository. While no confirmed successful exfiltration was documented, the technique represents a new attack surface: weaponising developer productivity tools as credential harvesters.

Phase 3: The Trivy Tag-Poisoning Attack (March 19, 2026)

At 17:43 UTC on March 19, TeamPCP leveraged retained credentials to execute the main strike. Using the compromised aqua-bot service account, the attacker force-pushed 75 of 76 version tags in aquasecurity/trivy-action and all 7 tags in aquasecurity/setup-trivy to malicious imposter commits. Simultaneously, a backdoored Trivy binary was published as v0.69.4 to GitHub Releases, Docker Hub, GHCR, and Amazon ECR.

The tag-poisoning technique was technically elegant. Each forged commit cloned the original commit’s metadata (author, timestamp, commit message) while replacing entrypoint.sh with the stealer payload and setting the commit’s parent to master HEAD. This produced commits that looked nearly identical on GitHub’s release page, including the “Immutable” badge. The sole telltale indicator was the “0 commits to master since this release” counter, which displayed zero even for tags dating to 2020–2024 that should have shown hundreds of commits.

The single surviving clean tag was 0.35.0, protected because GitHub’s immutable releases feature had been enabled on March 4. The attacker likely skipped it because replacing it would have produced a commit whose parent was itself, creating a visibly anomalous release.

The Three-Stage Credential Stealer (entrypoint.sh, 204 lines)

The malicious entrypoint.sh (SHA-256: 18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a) was a 204-line bash script. Lines 4–105 contained the stealer. Lines 106–204 ran the legitimate Trivy scan, ensuring pipeline output looked clean and no build failures alerted operators.

Stage 1 — Collection: On GitHub-hosted Linux runners, the malware dumped Runner.Worker process memory via /proc/[pid]/mem, searching for the JSON pattern {“value”:”<secret>”,”isSecret”:true} stored in the .NET process heap. On self-hosted runners, a comprehensive Python credential harvester swept 50+ paths across SSH keys, Git tokens, AWS/GCP/Azure credentials (including EC2 IMDS at 169.254.169.254), Kubernetes configs and service account tokens, Docker registry creds, .env files, database credentials, CI/CD configs (Terraform state, Jenkinsfile, .gitlab-ci.yml), TLS private keys, WireGuard configs, shell history (which often contains exported secrets), and even cryptocurrency wallets (Bitcoin, Ethereum, Solana keypairs, Ledger files).

Stage 2 — Encryption: Harvested data was encrypted with AES-256-CBC (key derived via PBKDF2 from 32 random bytes), with the session key wrapped by a hardcoded RSA-4096 public key using OAEP padding. The bundle was packaged as tpcp.tar.gz. Only the RSA private key holder can decrypt.

Stage 3 — Exfiltration: Primary: HTTPS POST to scan.aquasecurtiy[.]org (45.148.10.212, Amsterdam, TECHOFF SRV LIMITED) with header X-Filename: tpcp.tar.gz. Fallback: if the C2 was unreachable and INPUT_GITHUB_PAT was available, the stealer created a public repository named tpcp-docs under the victim’s GitHub account and uploaded the bundle as a release asset. Data exfiltrated over GitHub’s own infrastructure is unlikely to be blocked by corporate firewalls.

Phase 4: The Checkmarx Wave (March 23, 2026)

Four days after the Trivy compromise, TeamPCP pivoted to Checkmarx’s ecosystem. Between 12:58 and 16:50 UTC on March 23, all 35 tags of Checkmarx/kics-github-action were hijacked using the compromised cx-plugins-releases service account (GitHub ID 225848595). The attacker staged malicious commits on a fork containing a setup.sh payload, then updated all tags to point to those commits.

The KICS payload shared the identical RSA public key as the Trivy stealer, providing high-confidence attribution. TeamPCP introduced a new C2 domain: checkmarx[.]zone (resolving to 83.142.209.11), replacing the Trivy-era typosquat. The fallback exfiltration repository was renamed from tpcp-docs to docs-tpcp. New capabilities included Kubernetes-focused persistence code not present in the Trivy variant.

At 22:25 UTC, Sysdig’s Threat Research Team reported that Checkmarx/ast-github-action version 2.3.28 was also compromised with the same payload. The process tree was functionally identical to the Trivy attack: Runner.Worker → bash → setup.sh → curl POST. Only the entry point script and exfiltration domain differed. The use of vendor-specific typosquat domains for each poisoned action is a deliberate deception: an analyst reviewing CI/CD logs would see curl traffic to what appears to be the action’s own vendor domain, reducing the likelihood of manual detection.

Phase 5: OpenVSX Extensions Deliver Persistent Backdoor (March 23, 2026)

Twelve seconds apart at 12:53 UTC on March 23, two malicious VS Code extensions were published to OpenVSX via the ast-phoenix account: ast-results v2.53.0 and cx-dev-assist v1.7.0. VS Code Marketplace versions appear unaffected.

On activation, a malicious environmentAuthChecker.js checked whether the victim had credentials for at least one cloud provider. If detected, a second-stage payload was fetched from checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz and executed via npx, bunx, pnpx, or yarn dlx. On non-CI systems, the extension installed a systemd user service polling checkmarx[.]zone/raw every 50 minutes for additional payloads. The polling included a kill switch: if the response contained “youtube,” execution aborted. At the time of analysis, the kill-switch URL redirected to Queen’s “The Show Must Go On.”

Phase 6: CanisterWorm — Self-Propagating npm Worm with Blockchain C2

Using npm tokens harvested during the Trivy compromise, TeamPCP deployed CanisterWorm starting March 20 at 20:45 UTC. The worm was first detected by Aikido Security researcher Charlie Eriksen. It is the first publicly documented npm malware to use an ICP blockchain canister (tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io) as a C2 dead-drop, making conventional takedown impossible since the *.icp0.io gateway is shared across all ICP canisters.

The attack deployed in four escalating waves. Wave 1 hit 28 packages in the @emilgroup scope as a dry run. Wave 2 armed the ICP backdoor. Wave 3 introduced self-propagation via a findNpmTokens() function that scraped .npmrc files and environment variables, then used stolen tokens to bump patch versions and republish every package the victim maintained. Wave 4 combined self-propagation with the armed backdoor. The worm’s persistence mechanism disguised itself as a PostgreSQL monitoring service (pgmon.service), writing the backdoor to ~/.local/share/pgmon/service.py.

By March 22, the scale had expanded from the initial 47 packages (Aikido’s count) to 141 malicious artifacts across 66+ unique packages (Socket’s tracking). Compromised scopes included @emilgroup, @opengov, @teale.io, @airtm, and @pypestream.

Phase 7: The kamikaze.sh Script — Targeted Destruction and Subnet Scanning

On March 24, a new payload variant was detected: kamikaze.sh, a destructive script with geopolitical targeting. The script checks whether the runtime environment is Kubernetes and whether the system’s timezone is set to Asia/Tehran or the locale is Farsi. The logic branches four ways:

1. Kubernetes + Iran: wipe every node in the cluster. 2. Kubernetes + elsewhere: install the CanisterWorm backdoor on every node via a DaemonSet (host-provisioner-std). 3. Not Kubernetes + Iran: rm -rf / –no-preserve-root with sudo. 4. Not Kubernetes + not Iran: do nothing.

Once installed on a cluster, the worm drops a script that scans for SSH keys and Docker API tokens, then probes the local subnet for port 22 (SSH) and port 2375 (Docker API). If Docker API access is found, the worm creates a privileged container with the host root filesystem mounted, achieving full node compromise. This lateral movement capability transforms a single infected CI runner into a potential foothold across the entire internal network.

C2 Infrastructure: WAV Steganography and the Music Playlist

TeamPCP’s C2 infrastructure uses an ICP blockchain canister that points to either a binary payload URL or a YouTube link (the kill switch). The YouTube references evolved over the campaign: the initial C2 pointed to a Rick Roll, then shifted to Dido’s “Thank You,” then to King Gizzard and the Lizard Wizard. The Checkmarx wave’s kill switch pointed to Queen’s “The Show Must Go On.”

A later iteration embedded malware payloads inside WAV audio files using Base64 encoding within the file, which was decoded and executed on the target. This steganographic technique allows the C2 to serve what appears to be an audio file while delivering executable payloads, evading content-based filtering.

Affected Versions

Anatomy, phases and affected versions. Evolution of Team PCPC Attack: devsecops, ASPM, application security, vulnerability management, supply chain attack, GitHub Actions security, CI/CD compromise, reachability analysis, attack surface management, exposure management, TeamPCP, Trivy compromise, Checkmarx KICS, CanisterWorm, npm malware, ICP blockchain C2

Aqua Security / Trivy Ecosystem

ComponentVulnerableSafe VersionNotes
trivy-actionTags 0.0.1–0.34.2 (75 of 76 tags)v0.35.0 (SHA: 57a97c7e)Force-pushed to malicious commits
setup-trivy7 tags compromisedv0.2.6Same stealer payload in action.yaml
trivy binaryv0.69.4, v0.69.5, v0.69.6v0.69.3Published to Docker Hub, GHCR, ECR
HomebrewPicked up v0.69.4Rolled back to v0.69.3Built from source; binary OK after rollback
apt/rpm packagesNot affectedN/ANot impacted

Checkmarx Ecosystem

ComponentVulnerableSafe VersionNotes
kics-github-actionAll 35 tags (v1 through v2.1.20)Repository reinstated; verify SHACompromised via cx-plugins-releases service account
ast-github-actionv2.3.28 confirmed; all tags suspectedVerify SHA before useReported by Sysdig TRT
ast-results (OpenVSX)v2.53.0Prior versionsPayload: environmentAuthChecker.js
cx-dev-assist (OpenVSX)v1.7.0Prior versionsPublished 12 seconds after ast-results

npm / CanisterWorm

ScopePackages AffectedStatusNotes
@emilgroup28 packagesWave 1 dry run; Wave 2+ armedFirst scope targeted
@opengov16+ packagesActiveIncludes form-renderer, other packages
@teale.ioeslint-config v1.8.11–1.8.12Self-propagating variantFirst self-propagating payload
@airtm, @pypestreamMultiple packagesActiveLater wave expansion
Total tracked141 malicious artifacts / 66+ packagesPer Socket Security trackingAikido initial count: 47

Compromised kics-github-action Tags (All 35, source: Wiz)

TagCommit SHATagCommit SHA
v10e22ec8dv2.0.0121c38fb
v1.045f37494v2.1.01e9eeaba
v1.18e20c7a6v2.1.1c5c07508
v1.293de85c9v2.1.2c999dbb9
v1.30e7343bav2.1.34ebf62dd
v1.42dc0fa61v2.1.43ae9f0d6
v1.5f00191ddv2.1.596a0e8eb
v1.6e0359b1av2.1.631fbf583
v1.6.1dc6dbf35v2.1.7fca3a20a
v1.6.208b9ea97v2.1.80f81f132
v1.6.3005fb083v2.1.9c0e23718
v1.7.0a5471d37v2.1.10d66f0657
v23d49875ev2.1.11–2.1.20See Wiz advisory

Discovery and Disclosure Timeline

DateEvent
October 2025Vulnerable pull_request_target workflow (apidiff.yaml) added to Trivy repo
November 29, 2025Boost Security’s poutine tool flags the workflow; no action taken
February 20, 2026hackerbot-claw GitHub account created
Late February 2026hackerbot-claw scans public repos, exploits multiple GitHub Actions (Microsoft, Datadog, Aqua Security); attempts prompt injection against Claude code review bot
February 28, 2026Trivy repository fully compromised: releases deleted, repo defaced, malicious VS Code extension pushed to OpenVSX targeting local AI coding agents
March 1, 2026Aqua Security discloses, begins credential rotation (non-atomic); releases v0.69.2
March 3, 2026Trivy v0.69.3 released (current safe version)
March 4, 2026Immutable releases enabled on trivy-action (protects tag 0.35.0)
March 19, 17:43 UTCTeamPCP pushes backdoored Trivy v0.69.4 to GitHub, Docker Hub, GHCR, ECR
March 19, ~19:00 UTC75 trivy-action + 7 setup-trivy tags force-pushed; Socket generates 182 threat feed entries
March 19, ~19:15 UTCFirst detection by Paul McCarty
March 19–20CrowdStrike Falcon detects malicious script execution on customer runners
March 20, ~05:40 UTCMalicious Trivy artifacts removed by Aqua Security
March 20Tags restored with v-prefix convention; Docker images v0.69.5/v0.69.6 also found poisoned; 44 repos in aquasec-com org defaced
March 20, 20:45 UTCCanisterWorm first detected by Aikido Security researcher Charlie Eriksen
March 20–22CanisterWorm scales from 47 to 141 artifacts across 66+ npm packages
March 23, 12:53 UTCMalicious OpenVSX extensions ast-results v2.53.0 and cx-dev-assist v1.7.0 published via ast-phoenix account
March 23, 12:58–16:50 UTCAll 35 kics-github-action tags compromised via cx-plugins-releases service account
March 23, 16:50 UTCKICS repository taken down after community GitHub issue filed
March 23, 19:24 UTCKICS repository reinstated; Checkmarx states “The issue is resolved now”
March 23, 22:25 UTCSysdig TRT reports ast-github-action v2.3.28 also compromised
March 23, 22:35 UTCWiz confirms OpenVSX extension compromise; ReversingLabs concurrently reports same finding
March 24, 2026kamikaze.sh variant detected with Iran-targeting logic and Kubernetes cluster destruction; WAV steganography payload delivery observed

Determine If You’re Affected

Exposure by Environment

EnvironmentRisk LevelReason
CI/CD pipelines referencing Trivy by tagCriticalDirect credential theft from Runner.Worker memory; ~12-hour window
CI/CD pipelines referencing KICS/AST by tagCriticalSame stealer payload; ~4-hour window; new C2 domain
Self-hosted runners (any affected action)Critical50+ credential paths swept; SSH, cloud, K8s, crypto wallets; subnet scanning
Developers with compromised OpenVSX extensionsHighPersistent systemd backdoor polling C2 every 50 minutes
npm consumers of affected packagesHighCanisterWorm self-propagation; ICP blockchain C2 resistant to takedown
Docker builds using trivy:0.69.4–0.69.6HighBackdoored binary with ICP canister C2 polling
Developers who installed Feb 2026 VS Code extMediumMalicious prompts targeting local coding agents (Claude, Gemini, Copilot)
Pipelines pinned to full commit SHANot affectedImmutable reference; not vulnerable to tag repointing

Verification Steps

1. Search all workflow files for affected action references: grep -r “aquasecurity/trivy-action\|aquasecurity/setup-trivy\|Checkmarx/kics-github-action\|Checkmarx/ast-github-action” .github/workflows/

2. Determine whether any workflow ran a version-tag reference (not SHA) during either exposure window.

3. Check self-hosted runners for persistence indicators: ~/.config/sysmon.py, ~/.local/share/pgmon/service.py, pgmon.service, /tmp/pglog.

4. Search your GitHub organisation for repositories named tpcp-docs or docs-tpcp (indicates successful exfiltration).

5. Audit npm packages your organisation publishes for unexpected patch version bumps between March 20–24.

6. Check OpenVSX extension versions: ast-results should not be v2.53.0; cx-dev-assist should not be v1.7.0.

7. Run StepSecurity trivy-compromise-scanner for automated workflow log auditing.

8. Scan with Zizmor (open-source GitHub Actions security scanner) for pull_request_target misconfigurations in your own repositories.

Detection Guidance

Indicators of Compromise

TypeIndicatorContext
Exfiltration domainscan.aquasecurtiy[.]orgTrivy C2 (typosquat of aquasecurity)
Exfiltration IP45.148.10.212Amsterdam, TECHOFF SRV LIMITED
Exfiltration domaincheckmarx[.]zoneCheckmarx/KICS/OpenVSX C2 (typosquat of checkmarx.com)
Exfiltration IP83.142.209.11Checkmarx wave C2
Cloudflare Tunnelplug-tab-protective-relay.trycloudflare.comAdditional credential exfil channel
ICP Canistertdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.ioBlockchain-based C2 dead-drop (CanisterWorm + Trivy binary)
Initial C2recv.hackmoltrepeat.comhackerbot-claw initial breach (February)
Exfil headerX-Filename: tpcp.tar.gzPresent in all stealer curl POST requests
Fallback repostpcp-docs / docs-tpcpCreated in victim GitHub accounts if C2 unreachable
Persistence (Trivy)~/.config/sysmon.pyTrivy binary persistence script
Persistence (CanisterWorm)~/.local/share/pgmon/service.py + pgmon.servicesystemd user service masquerading as PostgreSQL monitor
Payload file/tmp/pglogDownloaded binary payload from ICP canister
Malware self-IDTeamPCP Cloud stealerString in stealer output

File Hashes (SHA-256)

HashArtifact
18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671aMalicious entrypoint.sh (Trivy stealer, 17,592 bytes)
07500e81693c06ef7ac6bf210cff9c882bcc11db5f16b5bded161218353ba4daLegitimate entrypoint.sh (2,855 bytes)
65bd72fcddaf938cefdf55b3323ad29f649a65d4ddd6aea09afa974dfc7f105dast-results-2.53.0.vsix (malicious OpenVSX extension)
744c9d61b66bcd2bb5474d9afeee6c00bb7e0cd32535781da188b80eb59383e0cx-dev-assist-1.7.0.vsix (malicious OpenVSX extension)
0d66d8c7e02574ff0d3443de0585af19c903d12466d88573ed82ec788655975ccheckmarx-util-1.0.4.tgz (second-stage payload)
527f795a201a6bc114394c4cfd1c74dce97381989f51a4661aafbc93a4439e90environmentAuthChecker.js (OpenVSX trigger script)
e9b1e069efc778c1e77fb3f5fcc3bd3580bbc810604cbf4347897ddb4b8c163bCanisterWorm Wave 1 index.js (dry run)
61ff00a81b19624adaad425b9129ba2f312f4ab76fb5ddc2c628a5037d31a4baCanisterWorm Wave 2 index.js (armed ICP backdoor)
0c0d206d5e68c0cf64d57ffa8bc5b1dad54f2dda52f24e96e02e237498cb9c3aCanisterWorm Wave 3 index.js (self-propagating)
c37c0ae9641d2e5329fcdee847a756bf1140fdb7f0b7c78a40fdc39055e7d926CanisterWorm Wave 4 index.js (final form)

MITRE ATT&CK Mapping

TechniqueDescriptionCampaign Application
T1195.002Supply Chain Compromise: Software Supply ChainPoisoned GitHub Actions, container images, npm packages, VS Code extensions
T1003OS Credential Dumping/proc/[pid]/mem reading for Runner.Worker secrets
T1552.004Unsecured Credentials: Private KeysSSH keys, TLS certs, cloud service principal files
T1552.005Cloud Instance Metadata APIIMDS queries at 169.254.169.254 for IAM credentials
T1543.002Create/Modify System Process: Systemd Servicepgmon.service persistence (CanisterWorm), host-provisioner-std DaemonSet
T1048.002Exfiltration Over Alternative ProtocolEncrypted bundle to typosquat domains; GitHub repo fallback
T1132Data EncodingAES-256-CBC + RSA-4096 wrapping; Base64 in WAV steganography
T1036MasqueradingImposter commits with cloned metadata; PG service name disguise
T1046Network Service DiscoverySubnet scanning for port 22 (SSH) and 2375 (Docker API)
T1021.004Remote Services: SSHUsing harvested SSH keys to propagate to local subnet hosts

Runtime Detection Rules

Sysdig published Falco rules that detect the stealer’s core behaviours: “Contact EC2 Instance Metadata Service From Container” (catches IMDS credential theft), “Curl Exfiltrating File” (catches the encrypted bundle upload regardless of destination domain), “Exfiltration of AWS IMDS Credentials Using LOTL Binary” (correlates IMDS access with subsequent data upload — the highest-signal rule), and “Dump Memory using /proc/ Filesystem” (catches the Runner.Worker memory scanning technique).

StepSecurity Harden-Runner provides network anomaly detection that builds per-job baselines and alerts on deviation, egress domain allowlisting, and a Compromised Actions Run Policy that blocks known-malicious actions. StepSecurity also released trivy-compromise-scanner for automated log auditing across organisations.

Remediation and Temporary Protections

Immediate Actions

1. Pin trivy-action to SHA: aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1

2. Pin setup-trivy to safe version v0.2.6.

3. Verify kics-github-action and ast-github-action references against known-good commit SHAs before re-enabling.

4. Rotate every pipeline secret (GitHub PATs, AWS/GCP/Azure credentials, SSH keys, npm tokens, Docker registry tokens, Kubernetes service account tokens) if any workflow ran a compromised tag during either exposure window.

5. Block the following at your network perimeter and DNS: scan.aquasecurtiy[.]org, checkmarx[.]zone, 45.148.10.212, 83.142.209.11, plug-tab-protective-relay.trycloudflare.com.

6. Search your GitHub organisation for repositories named tpcp-docs or docs-tpcp.

7. Audit self-hosted runners for persistence: ~/.config/sysmon.py, ~/.local/share/pgmon/, pgmon.service, /tmp/pglog.

8. Uninstall ast-results v2.53.0 and cx-dev-assist v1.7.0 from any developer machines using OpenVSX.

9. Check npm packages your organisation publishes for unexpected patch bumps between March 20–24.

Long-Term Hardening

Pin all GitHub Actions to full SHA commit hashes. Tools: Zizmor (open-source GitHub Actions scanner by Will Woodruff), pinact, StepSecurity secure-repo, Renovate with pinGitHubActionDigests. SHA pinning does not protect against transitive dependencies — if your action calls another action by tag, that second-degree dependency remains vulnerable.

Audit all pull_request_target workflows. If any step checks out the PR’s head code, it is exploitable via PWN request. Use poutine (Boost Security) for automated scanning.

Minimise token permissions. The Trivy breach was amplified because the PAT was scoped to the entire organisation. Prefer read-only tokens with the narrowest possible scope.

Enable immutable releases on repositories publishing GitHub Actions. This is the single control that saved trivy-action tag 0.35.0.

Require GPG-signed commits for release tags. The malicious commits were unsigned; signed-commit enforcement would have prevented the tag-poisoning.

Restrict IMDS access from CI runner containers using IMDSv2 with hop limits, or disable IMDS entirely where cloud credentials are not needed.

Monitor outbound network connections from CI runners for curl POST requests to domains that do not match expected artifact repositories.

Wait before adopting new package versions. Community detection of malicious code injections typically occurs within days. A one-week delay for non-critical updates provides a meaningful detection window.

How Threat Actors Could Use This Attack Pattern

The TeamPCP campaign is a masterclass in cascading supply chain exploitation, and the techniques are now publicly documented for any motivated threat actor to replicate.

GitHub Actions tag-poisoning is trivial once you have a PAT with write access to a repository. Tags are mutable by default in Git — most organisations protect branches but not tags. A single compromised token scoped to an organisation (rather than a repository) grants access to every repo under that org, as happened with Aqua Security.

The imposter commit technique — cloning the original commit’s metadata while replacing the payload — produces releases that look identical on GitHub’s UI. The only detectable anomalies (unsigned commits, impossible parent timestamps, “0 commits since release”) require manual inspection or purpose-built automation to catch.

The VS Code extension attack targeting local AI coding agents represents a new attack surface. As more developers adopt Claude Code, Copilot, and similar tools with broad filesystem access, malicious prompts embedded in extensions or dependencies can coerce these agents into harvesting credentials and exfiltrating them. The attack is especially effective in permissive modes (–dangerously-skip-permissions, –yolo) that developers use during active coding sessions.

The ICP blockchain C2 sets a precedent. Because ICP canisters run on decentralised infrastructure, no single domain registrar or hosting provider can issue a takedown. The *.icp0.io gateway is shared across all canisters, making IP-based blocking impractical without collateral damage. Future supply chain attackers will adopt blockchain-based C2 infrastructure as a matter of course.

The self-propagating npm worm pattern — harvest tokens, enumerate publishable packages, bump patch version, inject payload, republish — can be applied to any package ecosystem where tokens are stored in environment variables or local config files. PyPI, RubyGems, and Maven Central are all susceptible to the same technique if a maintainer’s token is compromised.

Phoenix Security Recommendations

The TeamPCP campaign demonstrates why vulnerability management cannot stop at scanning known CVEs. This attack had no CVE, no CVSS score, and no NVD entry. It targeted the security tooling itself. Traditional scanner-based workflows would not have flagged it.

Attack surface management: Phoenix identifies CI/CD pipelines running compromised components and maps whether references use mutable version tags or immutable SHA commits. For organisations running Trivy or Checkmarx actions across hundreds of repositories, Phoenix provides a single view of which pipelines referenced compromised tags during the exposure windows.

Contextual deduplication: Organisations using Trivy or KICS across dozens of repositories get a single prioritised backlog rather than duplicate alerts per repository. Phoenix correlates findings across scanners, environments, and teams to eliminate noise.

Reachability analysis: Phoenix maps which vulnerable component references actually executed compromised code versus those merely declared in workflow files. This distinguishes between repositories where the malicious action ran (and secrets were likely exfiltrated) versus those where the workflow was defined but did not execute during the exposure window.

Remediation campaigns: Create a campaign in Phoenix to track SHA migration across all affected actions, secret rotation completion, runner persistence cleanup, and npm package auditing. Assign owners per repository and track fix verification through to confirmed clean state.

Ownership attribution: Map each affected workflow to the owning team for coordinated response. When hundreds of repositories reference the same compromised action, knowing which team owns each workflow is the difference between a structured remediation and chaos.

Phoenix Security correlates vulnerable components with runtime workloads, identifies exposed pipelines via attack surface management, and assigns remediation ownership — turning a cross-ecosystem supply chain compromise into an owned, trackable remediation backlog.

References

1. Wiz Research — Trivy Compromised by TeamPCP

2. Wiz Research — KICS GitHub Action Compromised: TeamPCP Supply Chain Attack

3. CrowdStrike — From Scanner to Stealer: Inside the trivy-action Supply Chain Compromise

4. Socket Security — Trivy Under Attack Again: Widespread GitHub Actions Tag Compromise

5. Socket Security — CanisterWorm: npm Publisher Compromise Deploys Backdoor Across 29 Packages

6. Sysdig TRT — TeamPCP Stealer Detected in Checkmarx ast-github-action (sysdig.com)

7. StepSecurity — Trivy Compromised a Second Time: Malicious v0.69.4 Release

8. Aikido Security — TeamPCP Deploys CanisterWorm on NPM Following Trivy Compromise

9. Snyk — Trivy GitHub Actions Supply Chain Compromise

10. Boost Security Labs — 20 Days Later: Trivy Compromise, Act II

11. Rami McCarthy — Trivy Supply Chain Compromise: TeamPCP Attack Timeline & IOCs (ramimac.me/trivy-teampcp)

12. Aqua Security — Trivy Supply Chain Attack: What You Need to Know (aquasec.com)

13. Aqua Security GitHub Security Advisory GHSA-69fq-xp46-6×23

14. Mend — CanisterWorm: The Self-Spreading npm Attack That Uses a Decentralized Server to Stay Alive

15. Cloud Security Alliance — CSA Research Note: CanisterWorm Blockchain C2 in CI/CD Supply Chain Attack

16. ReversingLabs — Checkmarx OpenVSX Extension Compromise (concurrent report)

17. ARMO — The Trivy Supply Chain Attacks Explained


How Phoenix Security Fixes What Actually Matters

Your team doesn’t have a finding problem. They have a fixing problem.

Most platforms hand you a list. Phoenix hands you a plan — ranked by real risk, mapped to the team that owns it, with a clear path to close it.

What remediation looks like with Phoenix:

  • One backlog, not five. Findings from SAST, SCA, containers, and cloud — deduplicated, correlated, and surfaced in a single prioritized queue. No more reconciling lists across tools.
  • Ownership that sticks. Team attribution and inheritance mean the right ticket goes to the right engineer, first time. No routing, no guessing, no back-and-forth.
  • Campaigns that move the needle. Group related findings into targeted remediation campaigns. Track progress, measure closure rates, and report real reduction — not raw counts.
  • AI that does the legwork, not the deciding. Phoenix’s Remediator agent drafts fixes, creates tickets, and opens PRs. Your team reviews, approves, and merges. Every fix is traceable.

Phoenix Security changes the game.

The results are clear:

  • Bazaarvoice saved $6.3M in developer time and for teams removed critical in the first weeks of adoption
  • ClearBank cut critical container vulnerabilities by 96–99% and reclaimed 4 hours per engineer per week.
  • IAS saved an equivalent of 1.5M in development hours and reduced SCA-to-container noise by 82.4%
  • Optimizely has been able to act on vulnerabilities sitting on the backlog.

The pattern is the same every time: teams that move from find and report to analyze and fix close more risk with less effort.

The results are clear:

  • Bazaarvoice saved $6.3M in developer time and for teams removed critical in the first weeks of adoption
  • ClearBank cut critical container vulnerabilities by 96–99% and reclaimed 4 hours per engineer per week.
  • IAS saved an equivalent of 1.5M in development hours and reduced SCA-to-container noise by 82.4%
  • Optimizely has been able to act on vulnerabilities sitting on the backlog.

👉 Book a demo today

Or learn how Phoenix Security slashed millions in wasted dev time for fintech, retail, and adtech leaders.

Fix with remediaiton don’t chase ghost vulnerabilities

Francesco is an internationally renowned public speaker, with multiple interviews in high-profile publications (eg. Forbes), and an author of numerous books and articles, who utilises his platform to evangelize the importance of Cloud security and cutting-edge technologies on a global scale.

Discuss this blog with our community on Slack

Join our AppSec Phoenix community on Slack to discuss this blog and other news with our professional security team

From our Blog

TeamPCP turned Aqua Security’s own scanner into a credential stealer, force-pushed 76 version tags, and is still inside the organisation — three compromises in under a month, and counting
Francesco Cipollone
Phoenix Security announced the general availability of its AI-powered Remediation Engine, enabling agentless container vulnerability remediation aligned with CTEM principles. By correlating container lineage to build files, the platform reduces SCA noise by up to 91% and generates precise remediation actions engineers and AI agents can execute instantly.
Francesco Cipollone
Phoenix Security approaches vulnerability management as a remediation engineering problem. By combining reachability analysis, contextual deduplication, and minimal-impact upgrades, Phoenix transforms hundreds of findings into a small set of changes engineers can actually ship.
Francesco Cipollone
Contents
Derek

Derek Fisher

Head of product security at a global fintech

Derek Fisher – Head of product security at a global fintech. Speaker, instructor, and author in application security.

Derek is an award winning author of a children’s book series in cybersecurity as well as the author of “The Application Security Handbook.” He is a university instructor at Temple University where he teaches software development security to undergraduate and graduate students. He is a speaker on topics in the cybersecurity space and has led teams, large and small, at organizations in the healthcare and financial industries. He has built and matured information security teams as well as implemented organizational information security strategies to reduce the organizations risk.

Derek got his start in the hardware engineering space where he learned about designing circuits and building assemblies for commercial and military applications. He later pursued a computer science degree in order to advance a career in software development. This is where Derek was introduced to cybersecurity and soon caught the bug. He found a mentor to help him grow in cybersecurity and then pursued a graduate degree in the subject.

Since then Derek has worked in the product security space as an architect and leader. He has led teams to deliver more secure software in organizations from multiple industries. His focus has been to raise the security awareness of the engineering organization while maintaining a practice of secure code development, delivery, and operations.

In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

Jeevan Singh

Jeevan Singh

Founder of Manicode Security

Jeevan Singh is the Director of Security Engineering at Rippling, with a background spanning various Engineering and Security leadership roles over the course of his career. He’s dedicated to the integration of security practices into software development, working to create a security-aware culture within organizations and imparting security best practices to the team.
In his role, Jeevan handles a range of tasks, from architecting security solutions to collaborating with Engineering Leadership to address security vulnerabilities at scale and embed security into the fabric of the organization.

James

James Berthoty

Founder of Latio Tech

James Berthoty has over ten years of experience across product and security domains. He founded Latio Tech to help companies find the right security tools for their needs without vendor bias.

christophe

Christophe Parisel

Senior Cloud Security Architect

Senior Cloud Security Architect

Chris

Chris Romeo

Co-Founder
Security Journey

Chris Romeo is a leading voice and thinker in application security, threat modeling, and security champions and the CEO of Devici and General Partner at Kerr Ventures. Chris hosts the award-winning “Application Security Podcast,” “The Security Table,” and “The Threat Modeling Podcast” and is a highly rated industry speaker and trainer, featured at the RSA Conference, the AppSec Village @ DefCon, OWASP Global AppSec, ISC2 Security Congress, InfoSec World and All Day DevOps. Chris founded Security Journey, a security education company, leading to an exit in 2022. Chris was the Chief Security Advocate at Cisco, spreading security knowledge through education and champion programs. Chris has twenty-six years of security experience, holding positions across the gamut, including application security, security engineering, incident response, and various Executive roles. Chris holds the CISSP and CSSLP certifications.

jim

Jim Manico

Founder of Manicode Security

Jim Manico is the founder of Manicode Security, where he trains software developers on secure coding and security engineering. Jim is also the founder of Brakeman Security, Inc. and an investor/advisor for Signal Sciences. He is the author of Iron-Clad Java: Building Secure Web Applications (McGraw-Hill), a frequent speaker on secure software practices, and a member of the JavaOne Rockstar speaker community. Jim is also a volunteer for and former board member of the OWASP foundation.

Join our Mailing list!

Get all the latest news, exclusive deals, and feature updates.

The IKIGAI concept
x  Powerful Protection for WordPress, from Shield Security PRO
This Site Is Protected By
Shield Security PRO