Open Source · · 2 days
Vapi server SDK caught in the Phantom Gyp npm wave
On 2026-06-03 the Miasma worm republished 57 npm packages in under two hours, hiding execution in a 157-byte binding.gyp file instead of an install script. The largest victim was @vapi-ai/server-sdk, at more than 408,000 downloads a month.
Part of Miasma worm rode a build-config file through npm campaign
A self-replicating npm worm poisoned 57 packages in less than two hours on June 3, 2026, and did it without touching the preinstall or postinstall hooks that most supply-chain scanners watch. The largest package caught in the wave was @vapi-ai/server-sdk, the server-side SDK for the voice-AI platform Vapi, which StepSecurity put at more than 408,000 downloads a month.
The technique, which StepSecurity named "Phantom Gyp," abused node-gyp, the build tool Node.js uses to compile native addons. A binding.gyp file describes how to build those addons, and it can contain shell commands that node-gyp evaluates while resolving the build. The attacker needed 157 bytes: a command of the form "<!(node index.js > /dev/null 2>&1 && echo stub.c)", which quietly executed the package's own index.js during installation. Nothing appeared in package.json, so tools that inventory lifecycle scripts saw a clean package.
What index.js ran was a four-layer unpacking chain: a ROT-N Caesar cipher fed to eval(), an AES-128-GCM decryption layer, a loader that downloaded the Bun JavaScript runtime, and finally the Miasma payload itself. Once resident, it swept for npm, GitHub, AWS, GCP, Azure, HashiCorp Vault, and Kubernetes credentials, pulled GitHub Actions secrets out of runner memory, and wrote startup hooks into the configuration directories of AI coding assistants including Claude Code and Cursor, so that a developer opening the project again would re-execute it.
Stolen material went to GitHub, where the account liuende501 held 236 programmatically created repositories used as drop boxes. Snyk, which tracked the same activity as a node-gyp supply-chain compromise, counted more than 300 malicious versions across the affected packages. The worm closed the loop by using the credentials it collected to republish trojanized versions from any maintainer account it could reach, which is how a technique demonstrated on one project arrived in 56 others the same afternoon.
Notes
- StepSecurity counted 57 packages and more than 286 malicious versions published in under two hours on 2026-06-03. Snyk reported 57 packages and over 300 versions, tracking it as a node-gyp supply chain compromise.
- The binding.gyp payload was reported as "<!(node index.js > /dev/null 2>&1 && echo stub.c)". node-gyp evaluates shell commands in binding.gyp during install, so --ignore-scripts does block it by suppressing the implicit build.
- @vapi-ai/server-sdk was the largest single victim of this wave by download volume. Specific affected version identifiers were never published; four versions were reported as compromised.
- Exfiltration used 236 programmatically created repositories under the GitHub account liuende501. Repository descriptions referenced earlier security disclosures in reversed text.
Appendix · Affected releases
- Four versions were reported compromised on 2026-06-03 without published identifiers. These four are the only versions npm records as published that day: 0.11.1 at 23:26:29Z, 1.2.1 at 23:26:39Z, 0.11.2 at 23:28:37Z, 1.2.2 at 23:28:48Z.
- The registry corroborates it: the latest dist-tag points at 1.2.0 from 2026-04-22, older than 1.2.1 and 1.2.2. Rolling latest back to the last pre-incident release is the expected response, so 1.2.0 is the remediated release.
- All four versions remain published and installable by explicit version or a range that resolves to them. They were not unpublished, only removed from latest, so a pinned caret range can still reach them.
- The four SHA-256 values are measured complete npm archives for 0.11.1, 0.11.2, 1.2.1 and 1.2.2 in that order. OSSF MAL-2026-5209 maps the SHA-1 and SHA-512 to server-sdk-0.11.1.tgz.
Indicators
- filebinding.gyp
- malware_familyMiasma
- accountGitHub: liuende501
- file.claude/setup.mjs
References
- Miasma npm Supply Chain Attack: Self-Spreading Worm via Phantom Gyp - StepSecuritystepsecurity.io
- Node-gyp Supply Chain Compromise - Snyksnyk.io
- IronWorm and New Miasma Worm Variant Hit npm in Supply Chain Attacks - The Hacker Newsthehackernews.com
- OSSF MAL-2026-5209 package-integrity record for @vapi-ai/server-sdkraw.githubusercontent.com
Source record: oss/attacks/vapi-server-sdk/meta.yaml