Executive Summary
This assessment covers observed activity attributed to the threat actor TeamPCP (also tracked as PCPcat / ShellForce) based on reporting from five open-source intelligence publications between December 2025 and March 2026.
TeamPCP is a hybrid cybercrime group that targets cloud-native environments. Reporting documents the following distinct but linked operations:
- Mass exploitation of exposed cloud APIs (Docker, Kubernetes, Ray, Redis) affecting over 60 000 servers, 97% hosted on Azure and AWS, with deployment of XMRig cryptominers, Sliver C2 implants, and proxy tools.1
- Supply chain compromise of Aqua Security’s Trivy vulnerability scanner (v0.69.4), including its GitHub Actions (
trivy-action, setup-trivy), achieved through a compromised service account (aqua-bot). The backdoored Trivy binary harvested credentials from CI/CD environments and exfiltrated them to attacker-controlled infrastructure.2
- Deployment of CanisterWorm , a self-propagating npm worm seeded using credentials stolen via the Trivy compromise. CanisterWorm compromised more than 50 npm packages across multiple organisations by harvesting npm tokens and autonomously republishing itself to all packages owned by the token holder.3 4
- A Kubernetes cluster wiper with geopolitical targeting. A newly discovered payload (
kube.py) selects its behaviour based on system locale and timezone: systems configured for Iran (Asia/Tehran, fa_IR) are subjected to complete filesystem destruction via a privileged DaemonSet or direct rm -rf /, while non-Iranian Kubernetes environments receive the CanisterWorm backdoor installed as a persistent systemd service.5
Attribution confidence is assessed as high. All four operations share the same Internet Computer Protocol (ICP) blockchain canister C2 endpoint (tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io), consistent tooling (systemd persistence, Python backdoors, DaemonSet-based lateral movement), and overlapping infrastructure.5 3 1
The motivation for the Iranian-targeting wiper component is not established in available reporting. Whether this represents a geopolitical objective, a commissioned operation, or another purpose remains unknown. All other observed activity is consistent with financially motivated cybercrime (cryptojacking, credential theft, access brokering).5 1
Diamond Model Analysis
1. Attacker
| Attribute |
Detail |
| Designation |
TeamPCP (aliases: PCPcat, ShellForce) |
| Type |
Hybrid cybercrime group — infrastructure exploitation, data theft, access brokering, extortion, and destructive operations |
| Attribution Confidence |
High — consistent reuse of ICP canister C2 (tdtqy-oyaaa-aaaae-af2dq-cai), overlapping tooling, infrastructure, and TTPs across all documented campaigns |
| Observed Motivation |
Financial (cryptojacking, credential theft and brokering); destructive (Iran-targeted wiper) — motivation for the latter is unestablished |
| Operational Tempo |
Multiple campaigns observed between December 2025 and March 2026 |
TeamPCP demonstrates strong familiarity with cloud-native ecosystems (Kubernetes, Docker, CI/CD pipelines) and software supply chain mechanics (npm registry, GitHub Actions).5 3 2 1
2. Victimology
| Victim Category |
Detail |
| Primary Targets |
Cloud-native environments: Kubernetes clusters, Docker hosts, CI/CD pipelines, developer workstations |
| Supply Chain Victims |
Users of Aqua Security’s Trivy scanner (v0.69.4), trivy-action, setup-trivy GitHub Actions; consumers of 50+ compromised npm packages including @EmilGroup scope (42 000 weekly downloads) and @teale.io/eslint-config (7 000 weekly downloads)4 2 |
| Infrastructure Victims |
Over 60 000 servers globally, 97% hosted on Azure and AWS1 |
| Geopolitically Targeted |
Systems configured with Iranian locale/timezone (Asia/Tehran, fa_IR) are singled out for filesystem destruction via wipe and forced reboot5 |
| Downstream Impact |
Any organisation running npm install without pinned versions on compromised packages; any CI/CD pipeline using compromised Trivy versions or actions |
The victimology for the supply chain and cloud exploitation components is broad and indiscriminate. The Iranian-targeting wiper introduces a narrow, deliberate victim selection based on system locale and timezone checks.5
3. Capabilities
The following capabilities are documented across the observed campaigns:
- Supply Chain Compromise : Compromised the Trivy vulnerability scanner binary, associated GitHub Actions, and 50+ npm packages. Credentials stolen from the Trivy compromise were used to seed the CanisterWorm npm worm.4 2
- Self-Propagating Worm : CanisterWorm harvests npm tokens, enumerates all packages owned by the token holder, and republishes itself — propagating through the npm registry using only legitimate APIs.3 4
- Kubernetes-Native Lateral Movement : Deploys privileged DaemonSets with
tolerations: [operator: Exists] to schedule malicious containers on every node in a cluster, including control plane nodes. Uses hostPath volume mounts and privileged: true to escape containers to the underlying host.5
- Destructive Wiper : Payload (
kube.py) conditionally deploys a DaemonSet (host-provisioner-iran) that recursively deletes the host root filesystem and force-reboots every node, or executes rm -rf / --no-preserve-root on standalone hosts — exclusively targeting Iranian-configured systems.5
- Persistent Backdoor : Non-Iranian targets receive a Python backdoor (
runner.py) installed as a systemd service (internal-monitor) that polls the ICP canister C2 every 50 minutes for arbitrary binary payloads.5
- Credential Harvesting : Sweeps 50+ filesystem paths for SSH keys, AWS/GCP/Azure credentials, Kubernetes tokens, Docker configs, npm tokens, and cryptocurrency wallets. Dumps GitHub Actions Runner.Worker process memory for secrets.3 2
- Sandbox Evasion : 5-minute initial sleep delay, low-frequency C2 polling (every 50 minutes), User-Agent spoofing, and a
youtube.com kill-switch string.3
- Encryption : Exfiltrated data encrypted with AES-256-CBC / RSA-4096 hybrid encryption.2
- Additional Tooling : XMRig (cryptomining), Sliver C2 framework, FRPS/gost (proxying).1
4. Infrastructure
| Component |
Detail |
| C2 (Primary) |
ICP blockchain canister: tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io — decentralised, resistant to conventional takedown5 3 |
| Payload Staging |
Cloudflare Tunnels: souls-entire-defined-routes.trycloudflare.com (wiper/backdoor stager), plug-tab-protective-relay.trycloudflare.com (Trivy exfiltration)5 2 |
| Exfiltration Domain |
Typosquatted: scan.aquasecurtiy[.]org (45.148.10.212)2 |
| C2 Servers |
67.217.57.240, 44.252.85.168 (Sliver C2, staging)1 |
| Fallback Exfiltration |
GitHub Releases — creates tpcp-docs repository in victim’s account to upload stolen data2 |
| Code Repositories |
GitHub user DeadCatx3 — hosts CIDR scanning lists1 |
| Payload Delivery |
npm registry (legitimate), Docker Hub, GHCR, ECR (compromised Trivy images)4 2 |
| Kill Switch |
Backdoor checks if C2-provided URL contains youtube.com; if so, skips execution5 3 |
The ICP blockchain canister is a distinguishing infrastructure choice. The update_link method on the canister allows the attacker to rotate payloads without interacting with infected endpoints. Because the Internet Computer Protocol is a decentralised network, traditional takedown mechanisms (domain seizure, hosting provider abuse reports) are not applicable.3
Observed MITRE ATT&CK Techniques
Resource Development
| ID |
Technique |
Evidence |
| T1583.001 |
Acquire Infrastructure: Domains |
Typosquatted domain scan.aquasecurtiy[.]org registered for exfiltration; Cloudflare Tunnel URLs used for payload staging.5 2 |
| T1583.006 |
Acquire Infrastructure: Web Services |
ICP blockchain canister (tdtqy-oyaaa-aaaae-af2dq-cai) used as decentralised C2.5 3 |
| T1586.003 |
Compromise Accounts: Cloud Accounts |
Compromised aqua-bot service account; force-pushed malicious commits over 75/76 trivy-action tags and 7 setup-trivy tags.2 |
| T1608.002 |
Stage Capabilities: Upload Tool |
Malicious worm versions published to npm registry under legitimate package names.4 |
Initial Access
| ID |
Technique |
Evidence |
| T1195.001 |
Supply Chain Compromise: Compromise Software Dependencies |
28+ @EmilGroup npm packages and @teale.io/eslint-config compromised with worm payload.4 |
| T1195.002 |
Supply Chain Compromise: Compromise Software Supply Chain |
CanisterWorm republishes itself as --tag latest to all packages owned by stolen tokens, automatically infecting downstream consumers.3 |
| T1195.003 |
Supply Chain Compromise: Compromise Hardware/Software Delivery |
Trivy v0.69.4 binary, trivy-action, and setup-trivy GitHub Actions backdoored at source and distributed via GitHub Releases, Docker Hub, GHCR, ECR.2 |
| T1078.004 |
Valid Accounts: Cloud Accounts |
Stolen npm tokens and Kubernetes service account tokens used to authenticate to registries and clusters.5 3 4 |
| T1190 |
Exploit Public-Facing Application |
Exploitation of exposed Docker APIs, Kubernetes APIs, Ray dashboards, Redis servers, and CVE-2025-29927 (Next.js).1 |
Execution
| ID |
Technique |
Evidence |
| T1059.004 |
Command and Scripting Interpreter: Unix Shell |
Kamikaze DaemonSet executes find /mnt/host ... rm -rf and chroot /mnt/host reboot -f; stager script kamikaze.sh.5 |
| T1059.006 |
Command and Scripting Interpreter: Python |
kube.py orchestrates environment fingerprinting and DaemonSet deployment; runner.py / service.py / sysmon.py backdoors.5 3 2 |
| T1059.007 |
Command and Scripting Interpreter: JavaScript |
deploy.js and index.js execute worm propagation and token harvesting via Node.js.3 4 |
| T1610 |
Deploy Container |
Privileged DaemonSets deployed via kubectl apply to schedule malicious containers on every cluster node.5 |
Persistence
| ID |
Technique |
Evidence |
| T1543.002 |
Create or Modify System Process: Systemd Service |
Backdoor installed as systemd service internal-monitor (Kubernetes targets), pgmon (npm worm), sysmon.py (Trivy dropper) — all configured to auto-restart.5 3 2 |
| T1525 |
Implant Internal Image |
Malicious containers deployed with auto-restart policies in Docker environments.1 |
Privilege Escalation
| ID |
Technique |
Evidence |
| T1611 |
Escape to Host |
DaemonSets mount host root filesystem (hostPath: path: /) with privileged: true, enabling container escape to the underlying host.5 |
| T1548.003 |
Abuse Elevation Control Mechanism: Sudo |
poison_pill function attempts sudo -n rm -rf / --no-preserve-root on non-Kubernetes Iranian hosts.5 |
Defense Evasion
| ID |
Technique |
Evidence |
| T1070.004 |
Indicator Removal: File Deletion |
Stager script self-deletes after execution (rm -- "$0"); deploy.js restores original package.json and README after publishing.5 4 |
| T1036.005 |
Masquerading: Match Legitimate Name |
DaemonSets named host-provisioner-iran/host-provisioner-std; systemd services named internal-monitor, pgmon, sysmon.5 3 |
| T1036.003 |
Masquerading: Rename System Utilities |
Imposter commits spoofing legitimate maintainers (rauchg, DmitriyLewen) pushed to GitHub repositories.2 |
| T1027 |
Obfuscated Files or Information |
Backdoor code stored as base64-encoded strings decoded at deployment; exfiltrated data encrypted with AES-256-CBC/RSA-4096.5 2 |
| T1497.003 |
Virtualization/Sandbox Evasion: Time Based |
5-minute initial sleep delay before backdoor activation.3 |
Credential Access
| ID |
Technique |
Evidence |
| T1552.001 |
Unsecured Credentials: Credentials in Files |
Harvests .npmrc files, .env files, SSH keys, cloud credentials from 50+ filesystem paths.3 2 |
| T1552.004 |
Unsecured Credentials: Private Keys |
Collects SSH keys, GPG keys, AWS/GCP/Azure credentials, Kubernetes tokens, Docker configs.3 2 |
| T1003 |
OS Credential Dumping |
Dumps GitHub Actions Runner.Worker process memory (/proc/<pid>/mem) searching for secret patterns.2 |
| T1528 |
Steal Application Access Token |
npm tokens, GitHub tokens, and cloud provider tokens harvested and reused for lateral propagation.3 4 |
Discovery
| ID |
Technique |
Evidence |
| T1082 |
System Information Discovery |
Checks /etc/timezone, timedatectl, and LANG variable for Iranian indicators; checks GITHUB_ACTIONS environment variable.5 |
| T1613 |
Container and Resource Discovery |
is_k8s() function checks for Kubernetes service account paths and KUBERNETES_SERVICE_HOST environment variable.5 |
| T1526 |
Cloud Service Discovery |
Queries npm search API to enumerate all packages owned by compromised token holders.3 4 |
| T1083 |
File and Directory Discovery |
Sweeps 50+ filesystem paths for credentials, configuration files, and secrets.3 2 |
Lateral Movement
| ID |
Technique |
Evidence |
| T1570 |
Lateral Tool Transfer |
DaemonSets with tolerations: [operator: Exists] schedule on every node including control plane, achieving cluster-wide lateral movement.5 |
| T1080 |
Taint Shared Content |
Worm publishes malicious versions to all npm packages owned by compromised tokens, propagating via shared registry infrastructure.4 |
Collection
| ID |
Technique |
Evidence |
| T1005 |
Data from Local System |
Trivy payload enumerates secrets from environment and filesystem; Runner.Worker process memory scraped.2 |
Command and Control
| ID |
Technique |
Evidence |
| T1102 |
Web Service |
Backdoor polls ICP blockchain canister for payload URLs — decentralised C2.5 3 |
| T1008 |
Fallback Channels |
ICP canister exposes update_link method for payload rotation; GitHub Releases used as fallback exfiltration channel.3 2 |
| T1568 |
Dynamic Resolution |
Cloudflare Tunnel URLs used for dynamic payload staging and exfiltration.5 2 |
Exfiltration
| ID |
Technique |
Evidence |
| T1041 |
Exfiltration Over C2 Channel |
Encrypted credential bundles exfiltrated to scan.aquasecurtiy[.]org via HTTPS POST.2 |
| T1567.001 |
Exfiltration Over Web Service: Code Repository |
Fallback exfiltration creates tpcp-docs repository in victim’s GitHub account and uploads stolen data as release asset.2 |
Impact
| ID |
Technique |
Evidence |
| T1485 |
Data Destruction |
Kamikaze DaemonSet recursively deletes host root filesystem on Iranian-configured Kubernetes targets; poison_pill executes rm -rf / --no-preserve-root on standalone Iranian-configured hosts.5 |
| T1529 |
System Shutdown/Reboot |
After filesystem wipe, executes chroot /mnt/host reboot -f to force-reboot affected nodes.5 |
| T1496 |
Resource Hijacking |
XMRig cryptocurrency miners deployed across compromised infrastructure.1 |
| T1490 |
Inhibit System Recovery |
Filesystem destruction combined with forced reboot renders systems unrecoverable.5 |
Key Indicators of Compromise
| Type |
Value |
| ICP Canister (C2) |
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io |
| Cloudflare Tunnel |
souls-entire-defined-routes.trycloudflare.com |
| Cloudflare Tunnel |
plug-tab-protective-relay.trycloudflare.com |
| Typosquatted Domain |
scan.aquasecurtiy[.]org |
| IP Address |
45.148.10.212 |
| IP Address |
67.217.57.240 |
| IP Address |
44.252.85.168 |
| GitHub User |
DeadCatx3 |
| DaemonSet Names |
host-provisioner-iran, host-provisioner-std |
| Systemd Services |
internal-monitor, pgmon, sysmon |
| File Paths |
/var/lib/svc_internal/runner.py, /tmp/pglog, /tmp/.pg_state, ~/.local/share/pgmon/service.py, ~/.config/systemd/user/sysmon.py |
| Kill Switch |
C2 URL containing youtube.com |
Flare — TeamPCP Cloud-Native Ransomware ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Wiz — Trivy Compromised: TeamPCP Supply Chain Attack ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Mend.io — CanisterWorm: The Self-Spreading npm Attack That Uses a Decentralized Server to Stay Alive ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Aikido Security — TeamPCP Deploys Worm via npm / Trivy Compromise ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Aikido Security — TeamPCP Stage Payload: CanisterWorm Iran Wiper ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Discussion in the ATmosphere