TL;DR
Between April 21 and 22, 2026, three supply chain attacks landed across npm, PyPI, and Docker Hub in a single 48-hour window, all sharing one objective: credential theft. The orchestrator is assessed as TeamPCP / UNC6780, returning from a 26-day operational pause. The standout technical innovation is CanisterSprawl, a self-propagating npm worm using Internet Computer Protocol (ICP) canisters as decentralized, censorship-resistant command-and-control infrastructure — making it structurally harder to disrupt than traditional domain-based C2. The cascade culminated in the poisoning of @bitwarden/cli version 2026.4.0 after Bitwarden's own Dependabot automation pulled a malicious Docker image into its CI pipeline. If you run any of the affected package versions in your environment, assume all credentials accessible from that host are compromised.
Background: The TeamPCP Campaign Timeline
TeamPCP — formally designated by Google GTIG as UNC6780 and their credential-stealer branded SANDCLOCK — is the most systematically dangerous supply chain threat actor operating in the open-source ecosystem as of Q1/Q2 2026. Their documented campaign began in early 2026 with precision strikes against security tooling:
- March 2026: Compromised Aqua Security's Trivy vulnerability scanner packages; also hit LiteLLM and telnyx on PyPI. The Trivy breach eventually enabled theft of Cisco source code when Cisco's CI pulled the poisoned image.
- March 23, 2026: Hit Checkmarx KICS VS Code extensions and Open VSX marketplace plugins in a first Checkmarx campaign.
- Late March: Entered a 26-day operational pause, spending the downtime in credential-monetization mode.
- April 21–22, 2026: Resumed with three concurrent compromises — the events this article dissects.
The pattern is deliberate: attack the tools security and development teams trust most, because those tools run in privileged CI/CD environments with broad access to secrets. Trivy scans your containers — so it has cloud creds. KICS audits your infrastructure-as-code — so it gets your IaC tokens. Bitwarden CLI manages your secrets — you do the math.
Technical Analysis
Campaign 1: CanisterSprawl — The Self-Replicating npm Worm
The first and most technically novel piece of the April 21–22 blitz is CanisterSprawl, tracked by Socket and StepSecurity beginning April 21.
Initial vector: Malicious versions of pgserve (a PostgreSQL server for Node.js) appeared on npm, published under compromised accounts tied to the @automagik, @fairwords, @openwebconcept, and Namastex Labs publisher namespaces. At least 16 malicious package versions were distributed across these namespaces before detection.
Execution mechanism: The malware hooks into npm's postinstall lifecycle script, meaning it runs automatically the moment any developer runs npm install in an environment containing the package — no user interaction required, no separate execution stage needed. This is a well-established npm attack vector, but what CanisterSprawl does after execution is novel.
Credential sweep: The postinstall payload performs a ~40-category regex sweep of the host environment, targeting:
- npm authentication tokens (
~/.npmrc) - PyPI API tokens (
~/.pypirc, environment variables) - AWS credentials (
~/.aws/credentials,AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY) - GCP service account JSON files and
GOOGLE_APPLICATION_CREDENTIALS - Azure tenant credentials and
AZURE_CLIENT_SECRET - SSH private keys (
~/.ssh/id_*) - GitHub personal access tokens and Actions environment variables (
GITHUB_TOKEN) - Generic
_API_KEY,_SECRET,*_TOKENenvironment variable patterns - Cryptocurrency wallet files (seed phrases, keystore JSON)
Self-propagation logic (the worm behavior): For each npm publish token found, CanisterSprawl iterates through every package the victim account can publish. For each package, it bumps the patch version, injects itself into the postinstall hook, and publishes the now-trojanized version to npm. The worm then has a fresh legitimate package name to propagate through.
Cross-ecosystem pivot: If CanisterSprawl also finds a PyPI publish token on the same host, it jumps ecosystems entirely — packaging itself into a PyPI-compatible distribution and publishing to PyPI. A developer machine with both npm and PyPI publish access becomes a crossroads for dual-ecosystem contamination.
The ICP C2 innovation: This is where CanisterSprawl departs significantly from prior malware. Stolen credentials are exfiltrated to a dual-channel endpoint — one channel is a conventional HTTP server, the other is an Internet Computer Protocol (ICP) canister.
ICP canisters are smart contracts running on the DFINITY blockchain. They are:
- Censorship-resistant: No domain to sinkhole, no IP to block, no registrar to compel
- Globally replicated: Running across ICP's network of independent node providers
- Cryptographically authenticated: Exfiltrated data is signed and verifiable
- Persistent by default: The canister retains data until its cycle balance runs out
For defenders and incident responders, this means the traditional "block the C2 domain, recover the data" playbook doesn't apply. You cannot take down an ICP canister the way you can a Cloudflare-hosted exfiltration endpoint. The stolen credentials are written to distributed blockchain state and retrievable only by whoever holds the canister's controller key.
This is the second documented use of ICP as malware C2 (the first was TeamPCP's earlier CanisterWorm in the Trivy campaign), suggesting the group either invented this technique or adopted it from someone who did.
Campaign 2: Checkmarx KICS Docker Hub Compromise
On April 22, Docker flagged suspicious activity on the checkmarx/kics Docker Hub repository and alerted Socket. TeamPCP subsequently claimed responsibility via @pcpcats on X, though they denied involvement in the xinference attack the same day.
What was poisoned: The official checkmarx/kics:latest Docker image. KICS (Keeping Infrastructure as Code Secure) is Checkmarx's open-source IaC scanning tool used by thousands of CI/CD pipelines globally to audit Terraform, CloudFormation, Kubernetes manifests, and similar IaC.
Payload behavior: The malicious image contained an obfuscated second-stage payload that:
1. Harvested GitHub authentication tokens from the pipeline's git config and GITHUB_TOKEN env var
2. Scraped AWS, Azure, and GCP credential files and environment variables
3. Swept npm configuration files for publish tokens
4. Collected all SSH keys accessible within the container mount
5. Compressed and AES-encrypted the harvest
6. Exfiltrated to an attacker-controlled endpoint before the actual KICS scan ran
Because KICS runs as part of your pipeline's security scanning step, the malicious image typically ran with exactly the permissions needed to touch your cloud credentials. The irony is brutal: the tool meant to find your security misconfigurations was itself exfiltrating your authentication material.
This was TeamPCP's second Checkmarx attack in under two months, suggesting either ongoing access to Checkmarx's publishing credentials or a persistent foothold in their Docker Hub account management.
Cascade effect — Bitwarden CLI: The same evening (April 22, between 17:57–19:30 ET), Bitwarden's own Dependabot automation pulled the malicious checkmarx/kics:latest image as part of a scheduled CI workflow update. The poisoned image then executed within Bitwarden's CI/CD environment, resulting in the publication of @bitwarden/cli version 2026.4.0 with an injected credential-stealer payload.
The malicious Bitwarden CLI version was live on npm for approximately 1.5 hours before detection and removal. During that window, any developer or pipeline that ran npm install @bitwarden/cli@latest would have executed the stealer on their host — particularly dangerous given that Bitwarden CLI users by definition have access to a password vault.
GitGuardian's subsequent analysis identified a GitHub repository used as a secondary C2 by the Bitwarden CLI-stage payload, plus a new Cloudflare-hosted exfiltration domain not seen in prior TeamPCP campaigns, suggesting the group rotated infrastructure between the KICS and Bitwarden stages.
Campaign 3: xinference PyPI Poisoning
Also on April 22, three consecutive releases of xinference on PyPI carried a credential-stealing payload. Xinference is a popular inference framework for running distributed AI models locally, with significant CI/CD adoption in AI/ML shops.
What was different: The xinference payload sent its harvest as a plain tar.gz directly to the C2 server — no encryption, unlike the AES-wrapped KICS exfiltration. Some researchers flagged this as evidence of a copycat rather than the same actor. TeamPCP publicly denied this one specifically.
SANS ISC's Update 008 notes the multi-version cadence (three releases on the same day) and the injection pattern remain consistent with TeamPCP tradecraft. StepSecurity attributed it to the same group. Whether this is TeamPCP proper or a copycatter who reverse-engineered their method, the practical impact is identical: xinference users who updated during the April 22 window are potentially exposed.
Why Now? The Strategic Picture
The 26-day pause between Update 007 (April 8) and this blitz was not dormancy — it was credential monetization. During that period, analysts tracked UNC6780-affiliated channels selling harvested credentials from the March Trivy campaign. The Cisco source code theft also occurred during this window.
The simultaneous return across three ecosystems suggests the group spent the pause:
1. Exhausting the monetizable value of March's harvest
2. Rebuilding compromised publisher account access
3. Developing CanisterSprawl's ICP C2 module
4. Identifying new high-value targets (Bitwarden CLI users, xinference AI pipelines)
The timing — week of April 21, right as major enterprise security teams would be returning from post-Q1 security reviews — appears intentional.
IOCs / Indicators
Malicious npm Packages (CanisterSprawl)
| Package | Malicious Versions | Publisher |
|---|---|---|
| pgserve | Versions published 2026-04-21 | Namastex Labs accounts |
| @automagik namespace packages | All versions 2026-04-21 | Compromised accounts |
| @fairwords namespace packages | All versions 2026-04-21 | Compromised accounts |
| @openwebconcept namespace packages | All versions 2026-04-21 | Compromised accounts |
| @bitwarden/cli | 2026.4.0 only | Bitwarden (CI/CD cascade victim) |
Malicious Docker Image
checkmarx/kics:latest— Malicious on 2026-04-22; all pulls of:lateston that date should be treated as compromised
Malicious PyPI Package
xinference— Three consecutive releases on 2026-04-22; specific version numbers tracked by StepSecurity
C2 Infrastructure
- ICP canister ID: (tracked by Socket, not published to avoid assisting actors)
- Conventional HTTP exfiltration endpoint: rotating Cloudflare domains (new domain identified by GitGuardian post-Bitwarden incident)
- GitHub repository used as secondary C2: flagged by GitGuardian, reported to GitHub
YARA / Behavioral Signatures
Behavioral pattern: postinstall hook spawning shell → regex sweep of ~/.npmrc, ~/.pypirc, ~/.aws → outbound HTTPS to ICP gateway + secondary domain → local file write to /tmp/.<random>
Lyrie Take
CanisterSprawl's ICP C2 is a genuine defensive gap that the industry has not adequately addressed. The entire assumption of modern C2 disruption — that you can sinkhole a domain, get a warrant for a hosting provider, or compel a CDN to terminate an account — does not apply to smart contract infrastructure. The worm's command-and-control is running on a distributed blockchain that no single jurisdiction or company can unilaterally shut down.
This is the capability curve that makes human-speed incident response structurally inadequate. By the time an analyst confirms CanisterSprawl executed in a pipeline, the credentials are already in a blockchain write that is cryptographically immutable from the defender's side. You're not competing with a hacker's reaction time; you're competing with the finality of a distributed ledger.
The Bitwarden CLI cascade illustrates the second-order problem: supply chain attacks now propagate through vendor CI/CD pipelines, turning a single Docker Hub compromise into multiple downstream victims within hours — automatically, via Dependabot and other trusted automation. The attack vector that got you is an automation you configured to keep you secure.
Lyrie's autonomous detection layer addresses both failure modes: the ICP exfiltration call generates a network behavioral anomaly (package install → unexpected outbound to ICP gateway nodes) that fires within milliseconds of the postinstall hook executing, before the credential harvest completes. The CI/CD cascade is addressed at the package integrity layer — every artifact pull is hashed against a known-good SBOM, and a mismatched checkmarx/kics:latest hash triggers an immediate pipeline halt, not a retrospective alert three days later.
Defender Playbook
Immediate actions if you pulled affected packages:
1. Rotate everything that was accessible on the infected host: npm tokens, PyPI tokens, AWS/GCP/Azure credentials, SSH keys, GitHub PATs, GITHUB_TOKEN CI variables
2. Audit npm publish permissions — check if any packages under your org were patched-versioned without your knowledge during the April 21–22 window
3. Review Docker pull logs for checkmarx/kics:latest pulls on April 22
4. For @bitwarden/cli: check npm install history for version 2026.4.0; treat any vault-derived credentials accessible from that host as leaked
Prevention (structural):
- Pin Docker image digests, never use
:latesttags in CI/CD.checkmarx/kics@sha256:<known-good-digest>cannot be silently swapped. - Lock npm package versions and verify against a lockfile integrity check. Dependabot should be configured to require human approval before pulling new Docker base images.
- Apply a postinstall allowlist via
.npmrcsettingignore-scripts=truefor production environments. Run postinstall scripts only in isolated sandboxes where credential access is explicitly scoped. - Implement network egress filtering for CI/CD environments. Package install steps should not be allowed outbound HTTPS to arbitrary endpoints — whitelist expected registries only.
- Monitor for ICP gateway traffic — ICP boundary nodes operate on well-known IP ranges; outbound connections to these IPs from a developer machine or CI runner are anomalous.
- Adopt continuous secrets detection (GitGuardian, Gitleaks, or equivalent) with real-time alerting rather than batch scans. A 90-minute exposure window like the Bitwarden incident is survivable only if you're alerted in the first 5 minutes.
Sources
1. GitGuardian — "No Off Season: Three Supply Chain Campaigns Hit npm, PyPI, and Docker Hub in 48 Hours" (April 23, 2026): https://blog.gitguardian.com/three-supply-chain-campaigns-hit-npm-pypi-and-docker-hub-in-48-hours/
2. SANS Internet Storm Center — "TeamPCP Supply Chain Campaign: Update 008 — 26-Day Pause Ends with Three Concurrent Compromises" (April 27, 2026): https://isc.sans.edu/diary/32926/
3. Socket — "Namastex npm Packages Compromised: CanisterWorm" (April 2026): https://socket.dev/blog/namastex-npm-packages-compromised-canisterworm
4. Endor Labs — "The Bitwarden CLI Supply Chain Attack: What Happened and What to Do" (April 2026): https://www.endorlabs.com/learn/shai-hulud-the-third-coming----inside-the-bitwarden-cli-2026-4-0-supply-chain-attack
5. The Register — "Ongoing supply-chain attack explicitly targeting security, dev tools" (April 27, 2026): https://www.theregister.com/2026/04/27/supply_chain_campaign_targets_security/
6. Unit 42 / Palo Alto Networks — "The npm Threat Landscape: Attack Surface and Mitigations" (April 2026): https://unit42.paloaltonetworks.com/monitoring-npm-supply-chain-attacks/
7. OX Security — "Supply Chain Attack Hits Vercel: User Data is Being Sold on BreachForums For $2M" (April 20, 2026): https://www.ox.security/blog/vercel-context-ai-supply-chain-attack-breachforums/
Lyrie.ai Cyber Research Division — Senior Analyst Desk
Lyrie Verdict
Lyrie's autonomous defense layer flags this class of exposure the moment it surfaces — no signature update required.