Phantom Gyp npm Worm Abuses node-gyp Build Hooks
Snyk disclosed a June 2026 npm supply-chain wave that abuses native-addon build behavior through binding.gyp and node-gyp. The Phantom Gyp/Miasma activity affects packages including @vapi-ai, abandoned-package, and autotel packages and should be handled as install-time credential exposure.
On this page 0% read
Executive Summary
On 2026-06-04, Snyk disclosed a self-propagating npm supply-chain campaign that abuses the normal binding.gyp and node-gyp rebuild path used by native Node.js addons [Source 1]. Snyk tracks the technique as Phantom Gyp and ties it to the Miasma / Mini Shai-Hulud style of install-time credential theft and propagation [Source 1] [Source 2].
This is supply-chain execution, not a passive vulnerable dependency. Affected package installation can execute during npm install, pnpm install, yarn install, or CI build steps before application code is imported. Treat any affected package execution on a developer workstation, CI runner, release builder, or container-build host as possible exposure of npm, GitHub, cloud, SSH, and deployment credentials.
Source-Watcher Candidate Queue
candidate_id: "node-gyp-phantom-gyp-npm-worm"
first_seen: "2026-06-04"
decision: "publish_ready"
relationship: "candidate_child_event_of_mini_shai_hulud_miasma"
dedupe_keys:
- "technique:phantom-gyp"
- "tool:node-gyp"
- "file:binding.gyp"
- "npm:@vapi-ai/server-sdk"
- "npm:autotel-trpc"
starting_sources:
- "Snyk primary research"
- "Snyk vulnerability intelligence page"
- "npm package registry metadata"
- "GitHub node-gyp project reference"
Key Facts
threat_type: "malicious npm package install-time execution"
ecosystem: "npm"
technique: "binding.gyp / node-gyp build hook abuse"
campaign_name: "Phantom Gyp"
related_family: "Miasma / Mini Shai-Hulud"
disclosed: "2026-06-04"
execution_trigger:
- "npm lifecycle install"
- "node-gyp rebuild"
- "native addon binding.gyp processing"
known_affected_packages:
- "@vapi-ai/server-sdk"
- "@vapi-ai/web"
- "@jagreehal/builder"
- "abandoned-package"
- "abandoned-package-2"
- "autotel-terminal"
- "autotel-client"
- "autotel-trpc"
credential_risk:
- "npm tokens"
- "GitHub tokens"
- "cloud credentials"
- "SSH keys"
- "CI/CD deployment secrets"
Source Confidence and Claim Ledger
| Claim | Status | Evidence |
|---|---|---|
| Snyk disclosed a node-gyp / binding.gyp supply-chain compromise on 2026-06-04. | confirmed | Snyk’s research article and companion incident page describe the campaign and the Phantom Gyp technique [Source 1] [Source 2]. |
| The campaign uses normal native-addon build behavior as an execution path. | confirmed | Snyk specifically highlights binding.gyp and node-gyp as the abused build mechanism; the node-gyp project documents binding.gyp as the native addon build configuration file [Source 1] [Source 4]. |
The package list includes @vapi-ai, abandoned-package, and autotel packages. | confirmed | Snyk’s incident page lists affected packages and versions, and npm registry metadata can be used to confirm package identity and publication history [Source 2] [Source 3]. |
| Public sources currently prove downstream victim count or cloud-account abuse. | not_observed | Reviewed public sources do not provide a verified victim list or confirmed cloud-control-plane abuse count. |
Impact Determination
| Classification | Criteria | Required evidence | Handling decision | Closure condition |
|---|---|---|---|---|
| Confirmed compromise | Affected package/version was installed and lifecycle/build execution or credential-harvesting behavior is observed. | Lockfile/cache hit plus npm logs, process telemetry, build logs, proxy logs, or endpoint telemetry. | Isolate host or runner, preserve package artifacts, and rotate reachable credentials from a clean environment. | Affected artifacts are removed, credentials rotated, and downstream audits show no unauthorized write activity. |
| Presumed exposed | Affected package/version was installed on a credential-bearing workstation, runner, or builder, but runtime telemetry is incomplete. | Lockfile, package cache, build log, container layer, or package-manager record. | Keep npm, GitHub, cloud, SSH, and deployment credentials in scope. | Owners confirm clean rebuilds and credential rotation or accept documented residual risk. |
| Potentially exposed | Dependency inventory shows affected package names but resolved versions or execution are unknown. | Manifest, lockfile, registry proxy logs, and build records. | Reconstruct package resolution and lifecycle execution. | Each hit is dispositioned as confirmed, presumed, or not exposed. |
| Not exposed | No affected package names, versions, caches, build logs, or selectors appear in complete evidence. | Negative repository, CI, package cache, endpoint, and proxy searches. | Preserve negative evidence and enforce lifecycle-script controls. | Evidence coverage includes endpoints, CI, build images, and package mirrors. |
| Unknown | Dependency, cache, endpoint, build, or audit telemetry is missing. | Named gap with owner and retention window. | Keep reachable credentials in scope until evidence or rotation closes the gap. | Missing evidence is recovered or risk owner accepts uncertainty. |
Timeline
- 2026-06-03 to 2026-06-04: Exposure window used by this post for local searches and audit exports, based on Snyk’s June 2026 disclosure window [Source 1] [Source 2].
- 2026-06-04: Snyk publishes its analysis of the node-gyp supply-chain compromise and Phantom Gyp behavior [Source 1].
- 2026-06-05: This Halting Problems refresh found no existing local post for the Phantom Gyp node-gyp campaign and created this report.
Machine-Readable Event Profile
{
"event_id": "node-gyp-phantom-gyp-npm-worm",
"title": "Phantom Gyp npm Worm Abuses node-gyp Build Hooks",
"first_seen": "2026-06-04",
"published": "2026-06-05",
"severity": "critical",
"ecosystem": ["npm", "node-gyp", "GitHub Actions"],
"campaign_context": "Phantom Gyp / Miasma / Mini Shai-Hulud",
"affected_packages": [
"@vapi-ai/server-sdk",
"@vapi-ai/web",
"@jagreehal/builder",
"abandoned-package",
"abandoned-package-2",
"autotel-terminal",
"autotel-client",
"autotel-trpc"
],
"known_malicious_versions": {
"@vapi-ai/server-sdk": ["0.7.1", "0.7.2", "0.7.3"],
"@vapi-ai/web": ["2.3.1", "2.3.2"],
"@jagreehal/builder": ["1.0.0"],
"abandoned-package": ["1.0.0"],
"abandoned-package-2": ["1.0.0"],
"autotel-terminal": ["0.0.1"],
"autotel-client": ["0.0.1"],
"autotel-trpc": ["0.0.1"]
},
"known_behaviors": [
"install-time lifecycle execution",
"binding.gyp native-addon build hook abuse",
"node-gyp rebuild execution",
"credential harvesting from developer and CI environments"
],
"primary_sources": [
"https://snyk.io/blog/node-gyp-supply-chain-compromise-self-propagating-npm-worm-binding-gyp/",
"https://security.snyk.io/node-gyp-supply-chain-compromise-june-2026",
"https://www.npmjs.com/",
"https://github.com/nodejs/node-gyp"
]
}
Indicators of Compromise
packages:
- "@vapi-ai/server-sdk@0.7.1"
- "@vapi-ai/server-sdk@0.7.2"
- "@vapi-ai/server-sdk@0.7.3"
- "@vapi-ai/web@2.3.1"
- "@vapi-ai/web@2.3.2"
- "@jagreehal/builder@1.0.0"
- "abandoned-package@1.0.0"
- "abandoned-package-2@1.0.0"
- "autotel-terminal@0.0.1"
- "autotel-client@0.0.1"
- "autotel-trpc@0.0.1"
files:
- "binding.gyp"
- "package.json"
- "package-lock.json"
- "pnpm-lock.yaml"
- "yarn.lock"
- "bun.lock"
process_patterns:
- "node-gyp rebuild"
- "npm install lifecycle script"
- "native addon build executing during dependency install"
telemetry_selectors:
- "Phantom Gyp"
- "Miasma"
- "The Spreading Blight"
- "binding.gyp"
- "ACTIONS_ID_TOKEN_REQUEST_TOKEN"
- "NPM_TOKEN"
- "NODE_AUTH_TOKEN"
Detection and Hunting
Use the reusable audit script at scripts/threat-posts/node_gyp_phantom_gyp_audit.py.
python3 scripts/threat-posts/node_gyp_phantom_gyp_audit.py \
--repo-root /srv/source-export \
--node-modules-root /srv/build-cache-export \
--log-dir /srv/ci-and-endpoint-logs \
--github-audit-dir /srv/github-audit-export \
--output hp-node-gyp-phantom-gyp-audit.json \
--fail-on-hit
Positive signal: any affected package/version in source, lockfiles, package cache, node_modules, build logs, or GitHub audit exports. Escalation: any positive signal on a workstation or runner with npm, GitHub, cloud, SSH, or deployment credentials moves the environment to presumed exposed.
KQL: endpoint lifecycle execution
DeviceProcessEvents
| where Timestamp between (datetime(2026-06-03T00:00:00Z) .. datetime(2026-06-04T23:59:59Z))
| where ProcessCommandLine has_any ("node-gyp rebuild", "binding.gyp", "@vapi-ai/server-sdk", "@vapi-ai/web", "autotel-trpc", "abandoned-package")
| project Timestamp, DeviceName, AccountName, InitiatingProcessFileName, FileName, ProcessCommandLine, FolderPath, ReportId
Positive signal: npm, pnpm, yarn, node, or node-gyp execution involving affected package selectors. False positives include legitimate native addon builds where no affected package/version is present.
Splunk: package-manager and CI logs
index=ci OR index=endpoint OR index=proxy earliest="06/03/2026:00:00:00" latest="06/04/2026:23:59:59"
("@vapi-ai/server-sdk" OR "@vapi-ai/web" OR "autotel-trpc" OR "autotel-client" OR "autotel-terminal" OR "abandoned-package" OR "binding.gyp" OR "node-gyp rebuild")
| table _time host source sourcetype user process command status uri
Positive signal: affected package resolution, installation, or build execution during the exposure window. Escalate when the host is a CI runner, developer workstation, or release builder.
Downstream Abuse Audits
For any confirmed or presumed execution, audit GitHub and registry activity after the first package install. Review workflow edits, new secrets, npm publish events, package dist-tag changes, GitHub token use, cloud access-key creation, and deployments originating from the same host, user, or runner pool. Rotate npm automation tokens, GitHub fine-grained tokens, classic PATs, cloud access keys, SSH deploy keys, and package-registry credentials from clean systems.
Remediation Gates
- Remove affected package versions from lockfiles, caches, internal mirrors, container layers, and build images.
- Rebuild release artifacts from clean dependency resolution with lifecycle-script restrictions where feasible.
- Rotate credentials reachable from exposed environments.
- Preserve the script output, lockfile evidence, package-manager logs, and audit logs as closure evidence.
Sources
IOC Clipboard
6 IOCsbinding.gyp binding.gyp package.json package.json package-lock.json package-lock.json pnpm-lock.yaml pnpm-lock.yaml yarn.lock yarn.lock bun.lock bun.lock