# TeamPCP @antv Supply Chain Wave — Mini Shai-Hulud Multi-Ecosystem npm/GitHub Actions/VSCode Compromise

> Coordinated multi-ecosystem supply chain compromise (May 19, 2026) attributed by Wiz Research to TeamPCP — backdoors 200+ @antv npm packages, the actions-cool/maintain-one-comment and actions-cool/issues-helper GitHub Actions, and nrwl.angular-console v18.95.0 VSCode extension. Multi-stage infection retrieves payloads from orphaned GitHub commits, uses bun to install secondary payloads, harvests GitHub tokens/SSH keys/cloud credentials/browser secrets, and exfiltrates via attacker-created public GitHub repositories (description marker 'niagA oG eW ereH :duluH-iahS'). Persistence via Python backdoor at ~/.local/share/kitty/cat.py polling api.github.com for commits containing the C2 trigger string 'firedalazer'; backup C2 at m-kosche.com (185.95.159.32). Reuses Shai-Hulud family TTPs.

- **Published:** 2026-05-19T12:00:00Z
- **Last reviewed:** 2026-05-19T12:00:00Z
- **Canonical:** https://intel.threadlinqs.com/threat/TL-2026-0530
- **Card image:** https://intel.threadlinqs.com/og/threat/threat-intel-teampcp-antv-supply-chain-attack-tl-2026-0530.webp?v=ad0777d0 (Threadlinqs threat intel: TeamPCP @antv Backdoors 200+ Packages: Detection & IOCs (TL-2026-0530) — Critical severity, 27 IOCs, 9 detection rules.)
- **ID:** TL-2026-0530
- **Severity:** CRITICAL
- **Category:** SUPPLY_CHAIN
- **Status:** MONITORING
- **Actor:** TeamPCP
- **Detections:** 9 (1 shown free below) · **IOCs:** 27 (3 shown free below)

## Description

The TeamPCP @antv Supply Chain Wave (aka "Mini Shai-Hulud") is a coordinated, multi-ecosystem software supply chain compromise that reemerged on May 19, 2026, simultaneously affecting npm packages in the @antv visualization namespace, two widely-used actions-cool GitHub Actions (actions-cool/maintain-one-comment, actions-cool/issues-helper), and the nrwl.angular-console v18.95.0 VSCode extension. Wiz Research attributes the campaign with moderate confidence to the threat actor TeamPCP based on infrastructure overlaps, malware functionality, operational patterns, and tradecraft consistent with prior Shai-Hulud-family activity.

The infection begins when a developer or CI runner installs a compromised @antv npm package (200+ packages were published with malicious versions, e.g., @antv/g2 5.5.8/5.6.8, @antv/g6 5.2.1/5.3.1, @antv/util 3.4.11/3.5.11), executes a compromised GitHub Action workflow step, or activates the trojanized nrwl.angular-console v18.95.0 extension. Postinstall (or Action) code reaches out to GitHub-hosted infrastructure to retrieve additional payloads. Many of those payloads were stashed in orphaned GitHub commits, a deliberate evasion technique that decouples the malicious blob from any branch ref while keeping it reachable by commit SHA — the commit survives even if the repository is later cleaned.

Once the bootstrap stage runs, the malware uses `bun` (a fast JavaScript runtime/installer) to fetch and execute secondary payloads responsible for credential theft and persistence. The credential-stealing stage harvests a broad set of developer secrets: GitHub personal access tokens (from gh CLI, npm `.npmrc`, environment variables), SSH private keys (`~/.ssh/`), cloud provider credentials (AWS `~/.aws/credentials`, GCP application-default credentials, Azure CLI tokens), and browser-stored secrets (Chromium login data, cookies). Exfiltration is achieved by creating attacker-controlled **public** GitHub repositories from the victim's account and uploading the stolen data — repositories are tagged with the distinctive description string `niagA oG eW ereH :duluH-iahS` (the phrase "Shai-Hulud: Here We Go Again" reversed).

Persistence is established by dropping a Python backdoor at `~/.local/share/kitty/cat.py` (the "kitty" path masquerades as the Kitty terminal emulator's data directory). On macOS, persistence is anchored with a LaunchAgent plist at `~/Library/LaunchAgents/com.user.kitty-monitor.plist`; on Linux, with a systemd user unit at `~/.config/systemd/user/kitty-monitor.service`. The backdoor periodically polls the GitHub API endpoint `api.github.com/search/commits?q=firedalazer` looking for commits containing the C2 trigger string `firedalazer`. When a valid signed instruction is identified, the backdoor fetches and executes remote Python code, granting the operator ongoing arbitrary code execution. A fallback C2 channel is provided by the domain `m-kosche.com` (185.95.159.32). At time of disclosure Wiz had not observed the C2 channel active, suggesting the operators were in the staging phase.

The backdoor binary (cat.py / packaged blob) carries the following hashes: MD5 b06b126b9e26af03a7ef2f8b8e90d446 / SHA-1 783b4019fc5b942a29846132d28441c8fc31bed8 / SHA-256 fb5c97557230a27460fdab01fafcfabeaa49590bafd5b6ef30501aa9e0a51142.

Impact is severe because the affected components target high-trust environments: developer workstations (where local SSH keys and cloud credentials live), GitHub Actions runners (where repository write tokens and cloud OIDC trust live), and the @antv ecosystem (high-traffic data visualization libraries with deep transitive dependency reach — @antv/g2 and @antv/g6 alone are dependencies of thousands of downstream projects, including AI/ML dashboards using @antv/mcp-server-chart). Any organization that built, tested, or deployed an affected package version on May 19, 2026 must assume token, key, and credential compromise.

This wave is a continuation of the broader Shai-Hulud worm family of self-propagating npm supply chain attacks (originally documented in 2025 with the s1ngularity-repository pattern). TeamPCP's tradecraft reuses orphaned-commit payload hosting, GitHub-as-C2, and credential-harvest-then-republish propagation seen in earlier waves, but with a tighter focus on a single high-value npm namespace plus CI Actions and IDE extensions for broader developer reach. Recommended response is immediate: pin/remove affected versions, rotate ALL developer and CI secrets, audit repositories for unauthorized public repos with the marker description, hunt for the cat.py persistence file and the LaunchAgent/systemd units, and block egress to api.github.com search endpoints querying for `firedalazer` and to m-kosche.com / 185.95.159.32.

## MITRE ATT&CK

- T1586 Compromise Accounts
- T1583 Acquire Infrastructure
- T1608 Stage Capabilities
- T1587 Develop Capabilities
- T1195 Supply Chain Compromise
- T1195.002 Compromise Software Supply Chain
- T1199 Trusted Relationship
- T1059 Command and Scripting Interpreter
- T1059.006 Python
- T1059.004 Unix Shell
- T1204 User Execution
- T1543.001 Launch Agent
- T1543.002 Systemd Service
- T1053.003 Cron
- T1036 Masquerading
- T1027 Obfuscated Files or Information
- T1564 Hide Artifacts
- T1552.001 Credentials In Files
- T1552.004 Private Keys
- T1539 Steal Web Session Cookie
- T1555.003 Credentials from Web Browsers
- T1528 Steal Application Access Token
- T1083 File and Directory Discovery
- T1082 System Information Discovery
- T1526 Cloud Service Discovery
- T1005 Data from Local System
- T1102 Web Service
- T1102.002 Bidirectional Communication
- T1071.001 Web Protocols
- T1105 Ingress Tool Transfer
- T1008 Fallback Channels
- T1567 Exfiltration Over Web Service
- T1041 Exfiltration Over C2 Channel
- T1496 Resource Hijacking

## Free detection (Splunk SPL, Microsoft KQL, Sigma)

**TeamPCP @antv npm Postinstall Spawning bun Loader to raw.githubusercontent.com — Exploitation Phase** (`TL-2026-0530-SPL-001`)

Detects the Mini Shai-Hulud bootstrap stage: an npm/node/pnpm/yarn lifecycle script (postinstall of a compromised @antv package, an actions-cool GitHub Action runner step, or the nrwl.angular-console VSCode extension) spawning the 'bun' runtime as a child, which then reaches raw.githubusercontent.com to fetch a secondary payload hosted in an orphaned GitHub commit. Catches the exact TeamPCP infection chain on developer workstations and CI runners. Bun-as-loader is anomalous for projects that do not otherwise declare bun as a runtime — this pairing of package-manager parent + bun child + raw.githubusercontent.com fetch is the highest-fidelity exploitation signal in the campaign.

- **Languages:** Splunk SPL, Microsoft KQL, Sigma
- **ATT&CK:** T1195.002, T1059.001, T1059.004, T1105, T1036
- **Data sources:** sysmon, edr, microsoft_defender_for_endpoint, process_creation
- **Severity:** critical
- **Confidence:** high

### Splunk SPL

```spl
index=edr sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" (EventCode=1 OR EventCode=3)
| eval parent_lower=lower(ParentImage), proc_lower=lower(Image), cmd_lower=lower(CommandLine)
| where (match(parent_lower, "(\\\\|/)(npm|node|pnpm|yarn)(\\.exe)?$") OR like(parent_lower,"%code.exe%") OR like(parent_lower,"%code-helper%"))
    AND (match(proc_lower, "(\\\\|/)bun(\\.exe)?$") OR (match(proc_lower,"(\\\\|/)(curl|wget|node|powershell)(\\.exe)?$") AND like(cmd_lower,"%raw.githubusercontent.com%")))
| eval suspect_payload=if(like(cmd_lower,"%raw.githubusercontent.com%") OR like(cmd_lower,"%api.github.com%") OR like(cmd_lower,"%bun install%"),1,0)
| where suspect_payload=1 OR like(cmd_lower,"%@antv%") OR like(cmd_lower,"%actions-cool%") OR like(cmd_lower,"%nrwl.angular-console%")
| stats min(_time) as first_seen max(_time) as last_seen values(CommandLine) as cmd values(ParentImage) as parents by host, User, Image
| eval threat="TL-2026-0530 TeamPCP Mini Shai-Hulud bootstrap (npm/yarn/pnpm/node -> bun -> raw.githubusercontent.com)"
| table _time host User Image parents cmd threat
```

### Microsoft KQL

```kql
DeviceProcessEvents
| where Timestamp > ago(24h)
| extend parent = tolower(InitiatingProcessFileName), proc = tolower(FileName), cmd = tolower(ProcessCommandLine), pcmd = tolower(InitiatingProcessCommandLine)
| where parent in~ ("npm","npm.exe","node","node.exe","pnpm","pnpm.exe","yarn","yarn.exe","code.exe","code-helper")
    or pcmd has_any ("postinstall","@antv","actions-cool/maintain-one-comment","actions-cool/issues-helper","nrwl.angular-console")
| where proc in~ ("bun","bun.exe") or (proc in~ ("curl","curl.exe","wget","wget.exe","powershell.exe","node","node.exe") and cmd has "raw.githubusercontent.com")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| extend Threat = "TL-2026-0530 TeamPCP Mini Shai-Hulud — npm postinstall -> bun -> raw.githubusercontent.com payload fetch"
```

### Sigma

```yaml
title: TeamPCP Mini Shai-Hulud — npm Postinstall Spawning bun Reaching raw.githubusercontent.com
id: 4f1a30ce-1e10-4c8e-9c2b-0530aabb0001
status: experimental
description: Detects the TeamPCP @antv Mini Shai-Hulud bootstrap chain where an npm/node/pnpm/yarn (or VSCode-hosted nrwl.angular-console) process spawns the bun runtime, which then fetches a payload from raw.githubusercontent.com (orphaned-commit pattern).
references:
    - https://www.wiz.io/blog/mini-shai-hulud-teampcp-hits-antv-supply-chain
    - https://attack.mitre.org/techniques/T1195/002/
    - https://attack.mitre.org/techniques/T1105/
author: AII-Detector — ThreadLinqs Intelligence
date: 2026-05-19
tags:
    - attack.initial_access
    - attack.execution
    - attack.command_and_control
    - attack.t1195.002
    - attack.t1059.001
    - attack.t1059.004
    - attack.t1105
    - attack.t1036
    - threatlinqs.teampcp
    - threatlinqs.shai_hulud
logsource:
    category: process_creation
detection:
    selection_parent:
        ParentImage|endswith:
            - '/npm'
            - '/node'
            - '/pnpm'
            - '/yarn'
            - '\\npm.exe'
            - '\\node.exe'
            - '\\pnpm.exe'
            - '\\yarn.exe'
            - '\\Code.exe'
            - '/code-helper'
    selection_bun:
        Image|endswith:
            - '/bun'
            - '\\bun.exe'
    selection_payload:
        CommandLine|contains:
            - 'raw.githubusercontent.com'
            - 'api.github.com/repos'
            - 'bun install'
    selection_marker:
        CommandLine|contains:
            - '@antv/'
            - 'actions-cool/maintain-one-comment'
            - 'actions-cool/issues-helper'
            - 'nrwl.angular-console'
    condition: selection_parent and (selection_bun or selection_payload or selection_marker)
falsepositives:
    - Legitimate projects that intentionally use the bun runtime alongside npm/yarn (rare in mixed environments — exclude on known-bun repos)
    - Internal mirrors that intentionally proxy raw.githubusercontent.com for build assets
level: high
```

**Known false positives:**

- Projects that legitimately use the bun runtime as part of their toolchain alongside npm/yarn/pnpm
- CI build images that pre-warm caches from raw.githubusercontent.com for legitimate assets
- Internal developer tooling that wraps bun under a wrapper invoked from node

**Tuning notes:** Allowlist hosts where bun is a declared dependency (e.g., repos with bun.lockb in version control). Add allowlist for known internal mirrors of raw.githubusercontent.com. Tighten by requiring concurrent file write under node_modules/@antv/ within +/- 5s of the parent process spawn. If false-positive volume is high on dev workstations, scope the rule to CI runner hostnames first, then graduate to endpoints.

### 8 more detection rules (Splunk SPL, Microsoft KQL, Sigma), unlock with TL Creds

- VSCode nrwl.angular-console / npm Lifecycle Spawning bun Reaching api.github.com — Exploitation Phase (KQL) (locked: unlock with TL Creds)
- Developer Credential Enumeration by npm Postinstall / bun / python3 — Post-Exploitation (KQL) (locked: unlock with TL Creds)
- Anomalous Public GitHub Repository Creation with Shai-Hulud Marker — C2 / Exfil (KQL) (locked: unlock with TL Creds)
- Compromised @antv / actions-cool / nrwl Package Installation — Exploitation Phase (Sigma) (locked: unlock with TL Creds)
- cat.py / launchd / systemd-user Process Tree — Post-Exploitation Persistence Active (Sigma) (locked: unlock with TL Creds)
- TeamPCP Fallback C2 Egress to [indicator] / [indicator] — C2 Channel (Sigma) (locked: unlock with TL Creds)
- Shai-Hulud cat.py Backdoor Drop + Kitty-Masquerade Persistence — Post-Exploitation (locked: unlock with TL Creds)
- TeamPCP GitHub-as-C2 — firedalazer Search + [indicator] Fallback + Public-Repo Exfil (locked: unlock with TL Creds)

Sign up free to unlock the detection rules: https://threadlinqs.com/?modal=signup

## Sample indicators (3 of 27)

Defanged, TLP:CLEAR.

- IP address: `185.95.159[.]32`
- Domain: `m-kosche[.]com`
- File hash: `fb5c97557230a27460fdab01fafcfabeaa49590bafd5b6ef30501aa9e0a51142`

Full set of 27 indicators unlocks with TL Creds: https://threadlinqs.com/tl-creds

## Sources

- [The Worm That Keeps on Digging: TeamPCP Hits @antv in Latest Wave](https://www.wiz.io/blog/mini-shai-hulud-teampcp-hits-antv-supply-chain)
- [Nx (nrwl) Impact Report — angular-console 18.95.0 Compromise](https://github.com/nrwl/nx/security/advisories)
- [StepSecurity — actions-cool GitHub Actions Compromise Analysis](https://www.stepsecurity.io/blog/)
- [Socket — Mini Shai-Hulud Overall Compromise Tracker](https://socket.dev/blog/)
- [Original GitHub Issue Thread — @antv compromise](https://github.com/antvis/G2/issues)
- [MITRE ATT&CK T1195.002 — Supply Chain Compromise: Compromise Software Supply Chain](https://attack.mitre.org/techniques/T1195/002/)
- [Wiz prior coverage — Shai-Hulud worm campaign (2025)](https://www.wiz.io/blog/shai-hulud-npm-supply-chain-worm)

## Full data

The other 8 detection rules (Splunk SPL / Microsoft KQL / Sigma) unlock with TL Creds; a free account includes daily creds: https://threadlinqs.com/?modal=signup
Indicator values unlock with TL Creds, at a lower price on Red and Purple; AI agents can query rules and IOCs through the Threadlinqs MCP server (Purple): https://intel.threadlinqs.com/mcp

Canonical: https://intel.threadlinqs.com/threat/TL-2026-0530
