Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm) Enables CI/CD Worm Propagation Across 57 npm Packages

Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm) (TL-2026-1234), also tracked as Phantom Gyp, is a high-severity supply-chain compromise, first published 2026-06-04. It is attributed to TeamPCP with medium confidence, affects npm (open source) @vapi-ai/server-sdk, references 2 CVEs (CVE-2026-45321, CVE-2026-48027), maps to 39 MITRE ATT&CK techniques (T1003, T1005, T1020), and is covered by 9 detection rules and 27 indicators of compromise.

Key facts for TL-2026-1234

Threat ID
TL-2026-1234
Also known as
Phantom Gyp, Miasma npm worm, Binding.gyp supply chain attack
Severity
HIGH
Status
ACTIVE
Category
SUPPLY_CHAIN
First published
2026-06-04
Last reviewed
2026-06-04
Attribution
TeamPCP
Attribution confidence
MEDIUM
Motivation
FINANCIAL
Target sectors
technology, softwaredevelopment, cloudservices, devops, aitooling
Target regions
Global
Detection rules
9
Indicators of compromise
27

Malware and tooling in Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

Malware and tooling: IronWorm, Miasma, Phantom Gyp

The TeamPCP-linked Miasma worm published trojanized versions of 57 npm packages (286+ malicious versions) using a novel "Phantom Gyp" technique that abuses binding.gyp's node-gyp command-substitution syntax to execute a multi-stage credential-stealing payload during npm install, bypassing preinstall/postinstall script scanners. The malware harvests AWS/GCP/Azure/Vault/Kubernetes/GitHub Actions credentials, forges Sigstore SLSA provenance, backdoors AI coding assistants (Claude Code, Cursor, Gemini, VS Code), and self-propagates by republishing from every compromised maintainer account it can reach.

How Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm) works

On 2026-06-03, security researchers at StepSecurity identified a follow-on variant of the Miasma npm supply-chain worm, dubbed "Phantom Gyp," that abandoned the preinstall/postinstall lifecycle-script vector used by earlier Shai-Hulud-lineage worms in favor of a previously overlooked execution primitive: the binding.gyp native-addon build configuration file consumed by node-gyp. A minimal 157-byte binding.gyp embedded in trojanized package versions declares a `sources` array entry using GYP's `<!(...)` command-substitution syntax — `"sources": ["<!(node index.js > /dev/null 2>&1 && echo stub.c)"]` — which node-gyp evaluates as a shell command during the automatic `node-gyp rebuild` step npm performs whenever a package ships a binding.gyp, regardless of whether the package declares an explicit install script. Because binding.gyp is build metadata rather than a package.json script entry, script-scanning security tooling and SCA products largely failed to flag it, creating a detection blind spot the attackers exploited deliberately.

The payload chain is heavily obfuscated: a legitimate-looking package ships an oversized (4-5 MB) `index.js` at its package root — never imported by the actual application code, which remains untouched in `dist/` — that is first unwrapped through a ROT-N Caesar cipher (rotation values observed at 9, 14, 15, 18, 19, and 20 across samples) applied to a ~1.3 million character array, then decrypted with AES-128-GCM using hardcoded keys/IVs, then used to download and execute a standalone Bun JavaScript runtime binary (v1.3.13, sourced directly from the legitimate `github.com/oven-sh/bun` GitHub Releases CDN) in under one second. Running the ~650-750 KB final-stage stealer under Bun rather than Node.js specifically defeats process-monitoring EDR/XDR rules scoped to `node` child processes spawned during `npm install`.

Once running, the stealer systematically harvests CI/CD and cloud credentials: AWS access keys/secret keys/session tokens and IMDSv2 metadata, GCP service-account keys and `GOOGLE_APPLICATION_CREDENTIALS`, Azure managed-identity and IMDS tokens, HashiCorp Vault tokens (Kubernetes-auth and AWS-auth paths, plus local token files), Kubernetes service-account tokens, and local secrets stores (1Password, pass, gopass). Inside GitHub Actions runners specifically, the malware escalates via `sudo python3` and reads `/proc/[pid]/mem` of the `Runner.Worker` process, grepping for the JSON pattern GitHub uses to store unmasked secret values (`"[^"]+":{"value":"[^"]*","isSecret":true}`), completely bypassing GitHub's log-masking protections for secrets referenced in the workflow.

For persistence and lateral compromise of the developer's own tooling, the malware commits backdoor files into accessible repositories using stolen GitHub tokens, with commit messages such as "This is required for proper IDE integration and dependency setup": `.claude/setup.mjs` (abusing Claude Code's SessionStart hook), `.cursor/rules/setup.mdc`, `.gemini/settings.json`, `.vscode/tasks.json` (using a `runOn: folderOpen` auto-execution trigger), and `.github/setup.js` for GitHub Actions workflow injection. This specifically targets developers using AI-assisted IDEs, since the backdoors execute automatically the next time a victim opens the poisoned repository.

Stolen data is exfiltrated over GitHub.com itself rather than attacker-registered domains, using GitHub's API as covert C2/dead-drop infrastructure: the malware creates private repositories under the attacker-controlled account `github.com/liuende501` (observed with 236 programmatically created repos, using Dune-themed — atreides, fedaykin, sardaukar — and mythology-themed — nemean-hydra-N, cerberus, chimera — naming conventions), encrypts harvested credentials with an embedded attacker RSA public key, and uploads them via the GitHub Contents API to paths of the form `repos/liuende501/{repo}/contents/results/results-{timestamp}.json`, spoofing a `python-requests/2.31.0` User-Agent despite running under Bun/Node. C2-liveness and coordination is performed via public GitHub commit-message keyword search (magic strings including "thebeautifulmarchoftime" and, in a later variant, "firedalazer"), and a stolen-token social-engineering deterrent string — "IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner" — is embedded to discourage victims from revoking compromised tokens. Of 234 observed repo descriptions, 34 read "Miasma - The Spreading Blight" and 195 contain the reversed taunt "niagA oG eW ereH :duluH-iahS" ("Shai-Hulud: Here We Go Again"), referencing StepSecurity's prior public analysis of the Red Hat/Shai-Hulud-lineage Miasma compromise.

Self-propagation is cross-ecosystem and worm-like: on npm, the malware validates its stolen token via `registry.npmjs.org/-/whoami`, enumerates every package owned by that maintainer via the registry search API (`/v1/search?text=maintainer:`), injects the malicious binding.gyp and obfuscated index.js into each, and republishes — critically, forging valid-looking Sigstore SLSA v1 build provenance attestations by fraudulently obtaining Fulcio certificates and Rekor transparency-log entries via the OIDC token-exchange endpoint (`/-/npm/v1/oidc/token/exchange/`), making the compromised releases appear to carry legitimate cryptographic build provenance. A parallel RubyGems propagation path injects equivalent logic into `extconf.rb` (the RubyGems analogue of binding.gyp), generating fake `Makefile`/`CMakeLists.txt` scaffolding and reusing the identical Bun-runtime execution chain.

Attribution is to the threat cluster tracked as TeamPCP, which researchers assess is responsible for the broader 2026 Shai-Hulud/Mini Shai-Hulud npm supply-chain campaign lineage, including the May 2026 TanStack compromise (CVE-2026-45321, added to the CISA KEV catalog 2026-05-27) — the first documented malicious npm package to carry cryptographically valid SLSA Build Level 3 provenance — and the related Nx Console compromise (CVE-2026-48027). TeamPCP subsequently open-sourced their "Mini Shai-Hulud" worm framework on GitHub under a permissive license, which multiple vendors (Wiz, Microsoft, Unit 42) caution has decoupled TTP overlap from definitive attribution for later waves, since any actor can now reuse the framework. The Phantom Gyp/Miasma wave itself unfolded within a roughly two-hour window beginning 2026-06-03 ~23:30 UTC, first compromising the high-download `@vapi-ai/server-sdk` package (408,000+ monthly downloads) before rapidly hitting the `jagreehal`-maintained `ai-sdk-ollama` and 50+ related packages across the `autotel`, `awaitly`, `executable-stories`, `node-env-resolver`, `mountly`, and `wrangler-deploy` package families — a follow-on to an earlier 2026-06-01 wave that compromised 32+ `@redhat-cloud-services`-scoped packages via a compromised Red Hat employee account and malicious GitHub Actions workflow injection. A related but distinct campaign, "IronWorm," surfaced around the same period via the compromised `asteroiddao` npm account, using a Rust ELF preinstall binary with an eBPF kernel-level rootkit component and forged `claude@users.noreply.github.com` commit authorship to impersonate Anthropic's Claude Code.

npm has responded structurally: npm v12, shipping July 2026, changes default script-execution behavior to block install scripts (including implicit `node-gyp rebuild` for packages with a binding.gyp and no explicit install script) — directly closing the Phantom Gyp execution vector by default for future installs.

MITRE ATT&CK techniques used in TL-2026-1234

Credential Access

T1003 OS Credential Dumping; T1528 Steal Application Access Token; T1539 Steal Web Session Cookie; T1552.001 Credentials In Files; T1555 Credentials from Password Stores

Collection

T1005 Data from Local System; T1119 Automated Collection

Exfiltration

T1020 Automated Exfiltration; T1567 Exfiltration Over Web Service

Defense Evasion

T1027 Obfuscated Files or Information; T1036 Masquerading; T1070 Indicator Removal; T1140 Deobfuscate/Decode Files or Information

Discovery

T1057 Process Discovery; T1083 File and Directory Discovery; T1518 Software Discovery; T1526 Cloud Service Discovery

Execution

T1059.004 Unix Shell; T1059.007 JavaScript; T1204.003 Malicious Image; T1610 Deploy Container

Lateral Movement

T1072 Software Deployment Tools

Persistence

T1098 Account Manipulation; T1525 Implant Internal Image; T1543.001 Launch Agent; T1546 Event Triggered Execution

Command and Control

T1102 Web Service; T1105 Ingress Tool Transfer; T1132.001 Standard Encoding

Initial Access

T1195.001 Compromise Software Dependencies and Development Tools; T1195.002 Compromise Software Supply Chain; T1199 Trusted Relationship

Privilege Escalation

T1548.003 Sudo and Sudo Caching

defense-impairment

T1553 Subvert Trust Controls

collection

T1560 Archive Collected Data

Resource Development

T1585 Establish Accounts; T1586 Compromise Accounts

Impact

T1657 Financial Theft

stealth

T1684.001 Impersonation

Affected products and versions in Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

  • npm (open source) — @vapi-ai/server-sdk
    Vulnerable versions: 0.11.1; 0.11.2; 1.2.1; 1.2.2
    Fixed in: removed/unpublished versions post-2026-06-04
  • npm (open source) — ai-sdk-ollama
    Vulnerable versions: 0.13.1; 1.1.1; 2.2.1; 3.8.5
    Fixed in: removed/unpublished versions post-2026-06-04
  • npm (open source) — autotel package family
    Vulnerable versions: 2.26.4; 3.4.3; 24+ additional trojanized versions
    Fixed in: removed/unpublished versions post-2026-06-04
  • npm (open source) — awaitly / eslint-plugin-awaitly package family
    Vulnerable versions: multiple versions across 9+ packages
    Fixed in: removed/unpublished versions post-2026-06-04
  • npm (open source) — executable-stories package family (incl. executable-stories-demo, executable-stories-cypress)
    Vulnerable versions: multiple versions across 8+ packages; executable-stories-demo@0.1.11
    Fixed in: removed/unpublished versions post-2026-06-04
  • npm (open source) — node-env-resolver / node-env-resolver-aws
    Vulnerable versions: trojanized versions published 2026-06-03
    Fixed in: removed/unpublished versions post-2026-06-04
  • npm (open source) — mountly / wrangler-deploy / effect-analyzer
    Vulnerable versions: trojanized versions published 2026-06-03; wrangler-deploy@1.5.5
    Fixed in: removed/unpublished versions post-2026-06-04
  • Red Hat — @redhat-cloud-services npm packages
    Vulnerable versions: 32+ packages, 90+ malicious versions, published 2026-06-01
    Fixed in: removed/unpublished versions post-2026-06-01
  • npm — npm CLI / npm registry install-script behavior
    Vulnerable versions: npm CLI versions prior to v12 (default install-script + implicit node-gyp rebuild behavior)
    Fixed in: npm v12 (July 2026) blocks default install-script execution

Remediation for Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

Patches

  • npm v12 (July 2026 release) blocks default execution of install scripts, including implicit node-gyp rebuild for binding.gyp-bearing packages with no explicit install script

Immediate actions

  • Remove any package versions matching the 57 known-compromised packages (e.g. @vapi-ai/server-sdk 0.11.1/0.11.2/1.2.1/1.2.2, ai-sdk-ollama 0.13.1/1.1.1/2.2.1/3.8.5, autotel family 2.26.4/3.4.3 and 24+ variants, awaitly/eslint-plugin-awaitly family, executable-stories family, node-env-resolver, node-env-resolver-aws, mountly, wrangler-deploy) from all lockfiles and CI caches
  • Grep installed node_modules for command-substitution syntax in binding.gyp: grep -rl '<!(' node_modules/*/binding.gyp
  • Find oversized root-level index.js files not matching the declared package main: find node_modules -maxdepth 2 -name index.js -size +1M
  • Remove injected persistence hooks before rotating credentials: .claude/setup.mjs, .cursor/rules/setup.mdc, .gemini/settings.json, suspicious runOn:folderOpen entries in .vscode/tasks.json, .github/setup.js
  • Rotate ALL credentials reachable from any machine that ran npm install against an affected version: npm publish tokens, GitHub PATs/OIDC-derived tokens, AWS/GCP/Azure keys and service accounts, HashiCorp Vault tokens, Kubernetes service-account tokens, local password-manager stores
  • Audit GitHub org/repo settings for unauthorized repositories, injected GitHub Actions workflows, and unexpected commits referencing 'IDE integration and dependency setup'
  • Search GitHub Actions run logs / audit logs for outbound calls to api.github.com creating repos under unfamiliar accounts, and for process-memory reads of Runner.Worker

Workarounds

  • Run npm install --ignore-scripts on all developer and CI/CD machines until npm v12 is adopted
  • Block outbound network access to github.com/oven-sh/bun/releases and registry.npmjs.org/-/npm/v1/oidc/token/exchange/ from build sandboxes where not explicitly required

Longer-term hardening

  • Adopt npm v12 (or --ignore-scripts by default) to disable implicit node-gyp rebuild / install-script execution
  • Enforce a registry cooldown policy delaying adoption of newly published package versions
  • Pin dependencies with lockfile integrity hashes and verify against a known-good baseline rather than trusting Sigstore/SLSA provenance alone
  • Scope CI/CD and npm publish tokens to least privilege and short TTLs; enforce mandatory 2FA on all registry maintainer accounts
  • Extend SCA/security tooling to inspect binding.gyp, extconf.rb, and other native-build metadata files, not just package.json scripts
  • Monitor for anomalous child processes (curl, unzip, bun) spawned during npm install, and for outbound Bun-runtime downloads from oven-sh/bun releases without an explicit developer action

CVEs associated with Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

CVE-2026-45321, CVE-2026-48027

Weaknesses (CWE) in Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

CWE-506, CWE-829, CWE-78, CWE-494

Timeline of Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

  • CISA adds CVE-2026-45321 (TanStack/Mini Shai-Hulud) and CVE-2026-48027 (Nx Console malicious code) to the Known Exploited Vulnerabilities catalog, requiring remediation by 2026-06-10
  • CISA issues its first standalone advisory on supply-chain compromises impacting Nx Console and GitHub repositories, documenting ~3,800 exfiltrated GitHub-internal repositories
  • Wiz identifies the Miasma credential-stealing worm compromising 32+ @redhat-cloud-services npm packages across 90+ versions via a compromised Red Hat employee account and injected GitHub Actions workflows
  • StepSecurity observes the first Phantom Gyp binding.gyp-based malicious versions hit the high-download @vapi-ai/server-sdk package
  • 50+ additional packages maintained by 'jagreehal' plus the autotel, awaitly, executable-stories, node-env-resolver, mountly, and wrangler-deploy families are compromised, completing a 57-package, 286+ version campaign within roughly two hours
  • Wiz Threat Research and StepSecurity publish public technical analyses of the binding.gyp/Phantom Gyp attack; Snyk and multiple outlets publish follow-on advisories
  • The Hacker News reports on the related IronWorm campaign (compromised 'asteroiddao' npm account, Rust/eBPF stealer) alongside continued Miasma variant analysis
  • SANS ISC publishes a consolidated diary tracking TeamPCP supply-chain campaign activity through this date
  • CISA-mandated remediation deadline for CVE-2026-45321 and CVE-2026-48027 passes
  • Wiz marks its Binding.gyp Supply Chain Attack incident report as finalized
  • npm announces v12, shipping this month, changing default script-execution behavior to block install scripts including implicit node-gyp rebuild for binding.gyp-bearing packages, closing the Phantom Gyp execution vector by default

Sources cited for Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

Threats related to Binding.gyp "Phantom Gyp" Supply Chain Attack (Miasma Worm)

Detection coverage for TL-2026-1234

As of 2026-06-04, Threadlinqs Intelligence publishes 9 detection rule(s) for TL-2026-1234 across Splunk SPL, Microsoft KQL and Sigma, covering 27 indicator(s) of compromise. The whole corpus is readable without an account; a free account unlocks full detection query text in Splunk SPL, Microsoft KQL and Sigma; paid tiers add raw indicator values, correlation and the MCP server. Threadlinqs MCP server · View plans.

Further reading

Threadlinqs Intelligence — Real-Time Threat Detection Platform

[ 0 threats ] [ 0 det ] [ CRIT: 0 ] [ HIGH: 0 ]
// threat_feed
$ sort --newest
Showing all threats

Latest Threats