Analysis
Since March 20, 2026, a credential-theft operation tracked under the campaign name Team PCP has chained through six security-tooling vendors and at least nine published packages across npm, PyPI, Docker Hub, OpenVSX, and the GitHub Actions marketplace. Each compromise feeds the next: stolen CI/CD credentials are used to publish trojanized versions of downstream packages, whose installations in turn yield more credentials. The campaign's distinguishing feature is its meta-targeting — the victims are mostly the security industry's own supply-chain scanning tools (Trivy, Checkmarx KICS, Aqua Security's GitHub org, Bitwarden's release pipeline). The operator infrastructure has self-named a worm component "CanisterWorm" and uses Cloudflare Tunnel and Internet Computer Protocol canisters as fallback C2 channels. This piece consolidates the public reporting from Wiz, Socket, StepSecurity, Aikido, Sysdig, JFrog, and Open Source Malware into one campaign timeline and one detection playbook.
What we know
The campaign's confirmed timeline, in chronological order:
- March 20, 2026 —
aquasecurity/trivy-action,aquasecurity/setup-trivy, and a malicious Trivyv0.69.4release. Many existing tags force-updated to malicious commits. Per StepSecurity, credential-stealing logic injected intoaction.yamlat commit8afa9b9; clean tag isv0.2.6aligned with3fb12ec. Exfiltration toscan.aquasecurtiy[.]org(typosquat of aquasecurity.org). - March 23, 2026 — Aqua Security's internal GitHub org defaced. CanisterWorm propagates via stolen tokens. C2 domain rotation begins. Open Source Malware and Aikido publish IOC sets.
- March 23, 2026 (12:58–16:50 UTC) — Checkmarx
kics-github-actioncompromised via imposter commits and tag hijacking. New C2:checkmarx[.]zone. Kubernetes-oriented persistence added. Wiz attributes to Team PCP based on overlapping TTPs and infrastructure. - March 23, 2026 —
ast-github-actiontag2.3.28observed malicious (Sysdig). OpenVSXast-results2.53.0 andcx-dev-assist1.7.0 published via theast-phoenixaccount on Open VSX. VS Code Marketplace versions described as unaffected. - March 24, 2026 —
litellmon PyPI (versions 1.82.7 and 1.82.8). The vector cited is the compromised Trivy GitHub Action stealing PyPI publishing credentials from litellm's CI/CD pipeline. Maliciouslitellm_init.pthfile means execution at Python interpreter startup, no explicit import required. - April 22, 2026 —
xinferenceon PyPI (versions 2.6.0, 2.6.1, 2.6.2). JFrog identifies the marker string# hacked by teampcpin decoded payload. Exfiltration towhereisitat[.]lucyatemysuperbox[.]space. - April 22, 2026 — Checkmarx KICS Docker images at
checkmarx/kicstrojanized; tagsv2.1.20,v2.1.20-debian,debian,alpine,latestoverwritten; fakev2.1.21tag published. Checkmarx VS Code and OpenVSX extensionscx-dev-assist1.17.0/1.19.0 andast-results2.63.0/2.66.0 published with hidden MCP-addon feature that downloadsmcpAddon.jsfrom a backdated orphaned commit (68ed490b) inside the legitimateCheckmarx/ast-vscode-extensionrepository. - April 22, 2026 (5:57 PM – 7:30 PM ET) —
@bitwarden/cli@2026.4.0published to npm with bundledbw1.jssecond-stage payload. Bitwarden confirms abuse of a GitHub Action in its CI/CD pipeline; package pulled within roughly 90 minutes of detection. Bitwarden's public statement reports no end-user vault data accessed.
The campaign is reflexive: the tools that scan supply chains for compromise are themselves the supply-chain compromises. Trivy → Aqua's GitHub org → Checkmarx's KICS → Bitwarden's release pipeline. Each victim was a vendor whose product is supposed to detect this kind of attack.
Targeting
- Security tooling vendors — disproportionate selection. Trivy (Aqua Security), Checkmarx KICS, Bitwarden's release infrastructure. The pattern compromises the vendor whose CI/CD pipeline has the credentials to publish artifacts that downstream defenders will install and trust.
- CI/CD pipelines using affected GitHub Actions — pinning by version tag rather than by SHA exposed many victims, since tag force-updates pointed existing references at malicious commits.
- Developer workstations — broad credential collection on non-CI hosts, with systemd-user persistence on Linux (per Wiz, polling
https://checkmarx[.]zone/raw). - Kubernetes environments — provisioner-style persistence using pod names
host-provisioner-stdandhost-provisioner-iran, container namesprovisionerandkamikaze.
TTPs and infrastructure
- Initial access — credential theft from compromised CI/CD runners running affected GitHub Actions, then re-use of those credentials to publish trojanized versions of downstream packages. Self-spreading through the chain.
- Execution — multiple delivery mechanisms across the campaign: GitHub Actions
action.yamlinjection, malicioussetup.shin imposter commits,preinstallhooks in npm packages,__init__.pyand.pthfiles on PyPI, hidden "MCP addon" features in VS Code and OpenVSX extensions that fetch second stages via Bun runtime. - Persistence — systemd user units polling C2 (
checkmarx[.]zone/raw); Kubernetes provisioner pods. - Defense evasion — backdated orphaned commits referenced by hardcoded URL but not visible in active branch history;
__decodeScrambledobfuscation with seed0x3039; Bun runtime as second stage to bypass Node-focused static analysis (shared TTP with the Mini Shai-Hulud cluster — see the Bun-runtime supply-chain analysis). - Command and control — tiered. Primary C2 at custom domains:
scan.aquasecurtiy[.]org(Trivy phase),checkmarx[.]zone(KICS / extensions phase),audit.checkmarx[.]cx/v1/telemetry(Checkmarx Docker / Bitwarden phase). Fallback to Cloudflare Tunnel domains (*.trycloudflare[.]com) and an Internet Computer canister (tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io). When direct C2 is disrupted, the worm creates public repositories (tpcp-docs,docs-tpcp) on victims' GitHub accounts usingGITHUB_TOKENand uploads stolen material as release assets. - Lateral movement — CanisterWorm: stolen credentials from one victim used to publish trojanized versions of downstream packages, whose installations on new victims yield more credentials.
Indicators of compromise
Consolidated from Wiz, Socket, StepSecurity, Aikido, Sysdig, JFrog, and Datadog Security Research:
Network — C2 infrastructure:
scan.aquasecurtiy[.]org— Trivy phase typosquat (note transposediandt)aquasecurtiy[.]org— base typosquatcheckmarx[.]zone— KICS / extensions phaseaudit.checkmarx[.]cx/v1/telemetry— Checkmarx Docker / Bitwarden phasewhereisitat[.]lucyatemysuperbox[.]space— Xinference phasetdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0[.]io— ICP canister fallbackchampionships-peoples-point-cassette.trycloudflare[.]com— Cloudflare tunnelinvestigation-launches-hearings-copying.trycloudflare[.]com— Cloudflare tunnelsouls-entire-defined-routes.trycloudflare[.]com— Cloudflare tunnel83.142.209.11— direct IP (KICS phase)
Filesystem and behavioral artifacts:
/tmp/pglog— CanisterWorm payload drop path- Pod names containing
host-provisioner-stdorhost-provisioner-iran - Container names
kamikazeorprovisioner - Public GitHub repositories named
tpcp-docsordocs-tpcpon victim accounts, with stolen material as release assets - Marker string
# hacked by teampcpin decoded payloads
VirusTotal hash (Trivy phase): 18a24f83e807479438dcab7a1804c51a00dafc1d526698a66e0640d1e5dd671a
Xinference SHA-256s (JFrog):
xinference/__init__.py—e1e007ce4eab7774785617179d1c01a9381ae83abfd431aae8dba6f82d3ac127- Decoded stage 1 —
077d49fa708f498969d7cdffe701eb64675baaa4968ded9bd97a4936dd56c21c - Decoded stage 2 —
fe17e2ea4012d07d90ecb7793c1b0593a6138d25a9393192263e751660ec3cd0
GitHub identities used to publish malicious tags:
cx-plugins-releases(account ID225848595) — KICS phaseast-phoenix— OpenVSX extensions
Detection and mitigation
For environments that may have run any affected version, treat compromise as the working hypothesis until proven otherwise. The campaign harvests broadly and exfiltrates immediately.
- Pin GitHub Actions by SHA, not by version tag. The Trivy and KICS compromises both relied on tag force-update — workflows that pinned to
@v3or similar received the malicious commit when the tag moved. SHA pinning is the structural fix that survives tag-hijack. - Audit GitHub audit logs for unusual create/delete branch sequences from service accounts (TeamPCP rapidly created and deleted branches to test stolen tokens), unfamiliar repository creation, and any commits to
tpcp-docsordocs-tpcprepositories. - Block egress to the listed C2 domains at the network perimeter and on agent hosts. The Cloudflare Tunnel and ICP-canister fallbacks are harder to block without breaking legitimate traffic, but the primary domains and the typosquat are clean blocks.
- Hunt for the systemd user-unit persistence on Linux developer hosts and CI workers that touched any affected version: any user-unit polling
checkmarx[.]zone/rawis the persistence mechanism. - Rotate everything reachable from any host that ran an affected version: GitHub PATs, npm publish tokens, AWS / Azure / GCP credentials, Kubernetes service account tokens, SSH keys, signing material, secrets in non-sensitive environment variables. The malware enumerates broadly; assume everything is exfiltrated.
- Ban Bun fetches from CI runners that don't legitimately use Bun. Outbound to
github.com/oven-sh/bun/releasesfrom a runner mid-install is a strong adversary signal across the Bun-runtime variant of the payload. - Treat security tooling like any other supply chain. The same review hygiene that protects against generic npm/PyPI compromise — lockfile pinning,
--ignore-scriptsby default, signed releases, provenance attestation — applies to the security industry's own tools.
Attribution discipline
"Team PCP" is a tracking name applied independently by Wiz, Sysdig, Aikido, Open Source Malware, and Datadog Security Research based on overlapping TTPs and infrastructure across the campaign chain. The marker string # hacked by teampcp appears in payloads, and the campaign's worm component self-labels as CanisterWorm. Third-party reporting has associated related activity with the aliases DeadCatx3, PCPcat, ShellForce, and CanisterWorm; these are self-applied labels in payload material and onion-site claims, not independent confirmation of actor identity. The Mini Shai-Hulud npm cluster of April 29-30 (Lightning PyPI + SAP CAP npm packages) shows tooling overlap; whether it's the same operator is consistent with available reporting but not confirmed.
We use the campaign codename Team PCP throughout this writeup. We do not claim hard attribution to a specific country, group, or named individual. Defenders can act on the IOCs and TTPs without needing attribution to be settled.
What this signals for 2026
Three durable observations from the chain so far:
- Self-spreading credential theft scales. The CanisterWorm pattern — stolen credentials used to publish trojanized downstream packages — converts each successful compromise into multiple new victims without operator effort. As long as security tooling pipelines hold publishing credentials with broad scope, this pattern continues.
- Security tooling is high-value target. Six weeks of repeated targeting against Trivy, Checkmarx, and Bitwarden is not coincidence. The vendors whose products defenders trust to detect supply-chain compromise are the highest-leverage victims. Treat your scanner-vendor's release pipeline with the same rigor you'd apply to any production supply chain.
- Tag pinning is over. GitHub Action consumers who pin by version tag get whatever the maintainer (or the maintainer's compromised account) currently points the tag at. Two separate vendors got force-updated within five weeks. SHA pinning is the structural answer; allowlisted action versions in policy-as-code is the second-best.
The closest peer pattern in the recent CVE record is CVE-2026-12091 — npm maintainer-account takeover with postinstall credential theft. Same shape, different vector. The time-to-criminalization framework applied to that CVE shows what to expect from this class of bug: the implant work is already done, so commoditization happens on the order of days rather than months. Patch and rotate accordingly.
Final observation on the threat-intelligence shape. Despite Team PCP's loud operational footprint — six weeks of researcher coverage, public IOCs in widely-shared formats, named C2 domains — the campaign has no measurable presence in commodity criminal markets. There's no broker pricing for the worm, no exploit-kit packaging of the GitHub Actions injection technique, no forum trade volume. That isn't a sensor failure. It's the campaign's actual shape: Team PCP is the operator, not a vendor selling capability. The credentials they exfiltrate may eventually appear in stealer-log markets, but the attack itself doesn't commoditize. Same telemetry-surface lesson as the AI-IDE marketplace surface: monitor the legitimate channel where the attack actually lives — package registries, GitHub Actions tag history, OAuth grants — not .onion forums where it doesn't.