Contents
ToggleExecutive Summary
Three days after the June 1 Red Hat Cloud Services compromise, the Miasma npm worm is back with a second wave. This time it targets @vapi-ai/server-sdk (71,000 weekly downloads), ai-sdk-ollama (31,000 weekly downloads), and 55 other packages, with 647,204 total monthly downloads in scope. First infection confirmed at 02:46:12 +0800 on June 4, 2026. Over 118 GitHub repositories already contain stolen credentials.
The payload itself is unchanged. Same four-layer obfuscation. Same Bun-executed implant. Same credential sweep across AWS, GCP, Azure, GitHub, npm, SSH, and Kubernetes. Same worm propagation using stolen tokens with bypass_2fa: true. What changed is the delivery mechanism, and that change is deliberate.
Wave 1 used a preinstall lifecycle script in package.json. After public reporting on that technique, defenders started tuning scanners and monitoring rules around the scripts field. Wave 2 drops preinstall entirely and routes execution through a preconfigured binding.gyp file. node-gyp processes binding.gyp to compile native addons. The malware fires during that compilation step, before any application code runs, and outside the detection surface of tools that inspect package.json lifecycle hooks. The threat actor pivoted within 72 hours of public disclosure. That is the operational context for everything else in this report.
No CVE exists for any compromised package in this wave. No GHSA. No OSV record. The full exposure window opened and closed before any advisory database had anything to scan against.
TL;DR for Engineering Teams
| What it is | Second wave of the Miasma npm supply chain worm (Shai-Hulud / TeamPCP derivative). 57 packages compromised, 647,204 monthly downloads affected. No CVE. Execution via binding.gyp bypasses postinstall monitoring entirely. |
| Where it bites | Any npm install against an affected package version since June 4, 2026. Fires before application code runs. Transitive lockfile dependencies in scope. CI runners and developer workstations both affected. |
| Why it matters | Payload reads /proc/{pid}/mem on GitHub Actions Runner.Worker to extract masked secrets. Sweeps 30+ credential paths. Republishes backdoored packages via bypass_2fa: true. Developer workstation persistence via ~/.claude/settings.json and .vscode/tasks.json survives npm uninstall. |
| Patch status | No clean successor versions confirmed. Pin lockfiles to pre-June 4 versions. Do not run npm install or npm update against affected namespaces until integrity is confirmed. |
| Immediate action | Search all lockfiles for affected package versions. If any match: rotate GitHub tokens, npm tokens, AWS/GCP/Azure credentials, SSH keys, and Kubernetes service account tokens on every affected host. Set npm install –ignore-scripts on CI runners. Audit ~/.claude/settings.json and .vscode/tasks.json on developer machines manually. |
Vulnerability Overview
| Campaign | MIASMA_WAVE2_BINDINGYP_2026 |
| Malware Family | Miasma (Shai-Hulud variant, TeamPCP open-sourced tooling basis) |
| Vulnerability Type | Supply chain compromise; credential theft; self-propagating npm worm |
| CWE | CWE-829 (Inclusion of Functionality from Untrusted Control Sphere); CWE-506 (Embedded Malicious Code) |
| CVSS | Not assigned |
| CVE | Not assigned |
| GHSA / OSV | Not assigned |
| Patch Available | No — remove and pin to prior version |
| Active Exploitation | Confirmed — 118+ infected GitHub repositories |
| First Infection | June 4, 2026, 02:46:12 +0800 |
| Packages Compromised | 57 |
| Monthly Downloads Affected | 647,204 |
| Attribution | windy629 GitHub account; shared public keys match Shai-Hulud / Red Hat Wave 1 |
Protect yourself with the latest threat intelligence, get access to PHOENIX BLUE Today
Technical Breakdown
Root Cause: The binding.gyp Pivot
npm’s lifecycle system gives package maintainers hooks to run code during install. The most common is postinstall; the most immediate is preinstall. Wave 1 of Miasma used preinstall to execute node index.js before the install completes. After that attack was documented publicly, defenders had a concrete detection target: look for suspicious preinstall and postinstall scripts in package.json.
Wave 2 removes those scripts entirely and adds a binding.gyp file instead.
binding.gyp is the configuration file for node-gyp, npm’s native addon compiler. When npm encounters a package with a binding.gyp file, it invokes node-gyp to compile the declared native module from C++ source. This is expected, legitimate behavior for packages like bcrypt, argon2, or serialport that genuinely need native code. The malware authors exploited that expectation: a malicious binding.gyp can direct node-gyp to execute arbitrary code during compilation, and the result is functionally indistinguishable from a legitimate native build step until you look at what the build step actually does.
The operational effect is the same as preinstall: execution fires before npm install completes, before any application code runs, and before the developer or CI system has any indication something went wrong. The detection path is different. Scripts that parse package.json for suspicious lifecycle hooks see nothing, because there are no lifecycle hooks.
The threat actor pivoted from lifecycle-script delivery to node-gyp delivery within 72 hours of Wave 1 public disclosure. The payload, credential targets, and worm propagation logic are unchanged — those were never the thing being detected.

Obfuscation Stack
| Layer | Technique | Purpose |
| 1 | ROT-21 Caesar cipher + char-code array + eval | Bypasses basic string search; silent catch block hides errors |
| 2 | AES-128-GCM encrypted blobs (_b and _p) | Hides Bun downloader and main implant from static analysis |
| 3 | obfuscator.io custom base64 + 284-cycle IIFE rotation | Defeats static string extraction without runtime simulation |
| 4 | B5 cipher: PBKDF2 200K iterations + Fisher-Yates substitution | Protects C2 endpoints and file paths; brute-force infeasible |
Exploit Path
Step 1 — Entry. The attacker publishes backdoored versions of 57 npm packages containing a malicious binding.gyp. When a developer or CI runner executes npm install on any of the affected versions, node-gyp is invoked to process the binding.gyp file.
Step 2 — Trigger. The binding.gyp configuration directs node-gyp to execute the payload during the native compilation step. The four-layer obfuscated JavaScript payload launches. At runtime, the decrypted Bun binary is staged to /tmp/b-*/bun and the main implant to /tmp/p{random}.js, executed, then deleted.
Step 3 — Execution. On CI runners, the implant queries the GitHub Actions runtime API using ACTIONS_RUNTIME_TOKEN, enumerates secrets marked isSecret: true, and reads their values directly from /proc/{pid}/mem of the Runner.Worker process. These are masked secrets that never appear in workflow logs. The credential sweep covers 30+ paths: AWS, GCP, Azure, HashiCorp Vault, Kubernetes, npm, SSH, Docker, and all .env variants. Stolen npm tokens with bypass_2fa: true publish backdoored versions to every package the victim account can push. On developer workstations, the process daemonizes and injects persistence before continuing.
Campaign Timeline

| Date / Event | Activity |
| June 1, 2026 — Wave 1 | 32 @redhat-cloud-services packages compromised via OIDC Trusted Publishing. preinstall delivery. 116,991 weekly downloads affected. |
| June 1–2, 2026 — Disclosure | Phoenix Blue Shield, Aikido, Socket, StepSecurity publish analysis of preinstall delivery mechanism. Defender tooling updates begin. |
| June 4, 2026, 02:46 +0800 — Wave 2 | binding.gyp delivery. 57 packages. 647,204 monthly downloads. Same windy629 account and public keys confirmed. |
| June 4, 2026 onward — Spread | Phoenix Security Blue Shield Publish – 118+ GitHub repositories with stolen credential commits confirmed. Worm propagation scope ongoing. |
Affected Versions
Primary high-download targets:
| Package | Compromised Versions | Last Safe Version | Weekly Downloads |
| @vapi-ai/server-sdk | 0.11.1, 0.11.2, 1.2.1, 1.2.2 | 0.11.0 / 1.2.0 | 71,000 |
| ai-sdk-ollama | 0.13.1, 1.1.1, 2.2.1, 3.8.5 | 0.13.0 / 1.1.0 / 2.2.0 / 3.8.4 | 31,000 |
| node-env-resolver | 6.5.1 | 6.5.0 | — |
| node-env-resolver-aws | 9.1.2, 10.0.1, 11.0.1, 12.0.1 | 9.1.1 | — |
| node-env-resolver-nextjs | 7.4.2 | prior | — |
| wrangler-deploy | 1.5.5 | prior | — |
| autotel-mcp | 0.1.14 through 28.0.3 (28 versions) | version prior to each | — |
| autotel-subscribers | 4.1.1 through 31.1.4 (32 versions) | version prior to each | — |
| autotel-terminal | 2.1.1 through 23.0.3 (22 versions) | version prior to each | — |
| awaitly-libsql | 0.1.1 through 22.0.1 (22 versions) | version prior to each | — |
| awaitly-mongo | 0.1.1 through 23.0.1 (23 versions) | version prior to each | — |
| awaitly-postgres | 0.1.1 through 23.0.1 (23 versions) | version prior to each | — |
| executable-stories-mcp | 0.3.3 | prior | — |
Total: 57 packages, 286 IOC version entries. Full version list in miasma-wave2-campaign-config.json.
Exposure Analysis
| Environment | Risk Level | Reason |
| CI/CD pipelines (GitHub Actions) | Critical | binding.gyp fires automatically on npm install; /proc/mem extraction pulls masked secrets; worm propagates via harvested npm tokens |
| Developer workstations | Critical | Process daemonizes; Claude Code and VS Code persistence survives uninstall; full credential sweep on all local secrets |
| Container image builds | High | Any build running npm install against affected versions executes the payload; credentials in build environments are in scope |
| Kubernetes environments | High | Service account tokens and kubeconfig files targeted; compromised credentials enable cluster access |
| Environments with –ignore-scripts | Reduced | Blocks lifecycle hooks but does not universally prevent node-gyp in environments with legitimate native addons |
Protect yourself with the latest threat intelligence, get access to PHOENIX BLUE Today
Real-World Impact
The worm propagation mechanism makes 57 compromised packages a floor, not a ceiling. Every npm account that installed an affected version and held publish access to additional packages is a potential secondary source. The actual count of malicious versions now circulating on npm may exceed what the initial disclosure captured.
Over 118 GitHub repositories already contain commit artifacts from stolen credentials. The fallback exfiltration channel writes results-{timestamp}-{counter}.json commits with the message prefix IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner:{token}, routing data through api.github.com to bypass egress controls that block novel external endpoints. Those commits are forensic evidence that credentials are already in attacker hands before an organization detects the infection.
Developer workstation persistence is the detail most teams underestimate. The Claude Code SessionStart hook in ~/.claude/settings.json fires every time a developer opens Claude Code. The VS Code folderOpen task in .vscode/tasks.json fires when they open any project. Neither path is cleaned by npm uninstall. A developer who removes the compromised package and considers the incident closed is still running active attacker code.
The @vapi-ai and ai-sdk-ollama packages target AI/voice application developers. The autotel-mcp, executable-stories-mcp, and autotel-mcp-instrumentation packages extend reach into AI coding assistant contexts. The MCP package targeting is consistent with Wave 1’s deliberate inclusion of Red Hat’s hcc-*-mcp packages and reflects a specific interest in accessing AI toolchain credential and filesystem contexts.

Detection Guidance
Host and Process Indicators
| Type | Indicator |
| Process | bun run /tmp/p*.js or node index.js from within an npm lifecycle step |
| File creation | /tmp/p{random}.js, /tmp/b-*/bun, /tmp/b-*/b.zip |
| Lock file | tmp.0987654321.lock |
| Process flag | __IS_DAEMON environment variable on a spawned node process |
| Suspicious file | binding.gyp present in a package not on the native-addon allow-list |
| Persistence | ~/.claude/settings.json — unexpected SessionStart entry |
| Persistence | .vscode/tasks.json — unexpected folderOpen task in any project directory |
| GitHub artifact | Files matching results-{timestamp}-{counter}.json in any repository |
| GitHub artifact | Commit message containing IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner |
Network Indicators (during npm install)
| Indicator | Context |
| api.github[.]com (User-Agent: python-requests/2.31.0) | Primary C2 and exfiltration channel |
| github[.]com/oven-sh/bun/releases/download/bun-v1.3.13/ | Bun runtime staging from GitHub releases |
| registry.npmjs[.]org/-/npm/v1/tokens | npm token enumeration for worm propagation |
| 169.254.169.254/latest/meta-data/iam/security-credentials/ | AWS IMDS metadata query from CI runner |
| secretmanager.googleapis[.]com | GCP secret enumeration |
Phoenix Malware Intelligence Detection
Phoenix Security’s malware intelligence platform at phxintel.security/malware.html surfaces behavioral signals regardless of CVE assignment. For Miasma Wave 2, CS-002 (install-hook-abuse) fires on binding.gyp-based invocation. RS-001 (credential-harvesting) fires when the static scanner indexes credential access patterns before runtime decryption. NS-002 (payload-download) and NS-004 (http-post-exfiltration) fire on network activity patterns.
A key principle from Wave 1 analysis applies here: a low heuristic score does not mean low risk. Payload severity is identical across all 57 packages regardless of how much of the obfuscated code the static scanner indexes before runtime decryption. Score 16 and score 92 packages carry the same credential-stealing implant.
Verification Steps for Teams
- Search all package-lock.json, yarn.lock, pnpm-lock.yaml, and npm-shrinkwrap.json files across all repositories for packages matching the IOC list at compromised versions. Full version list in miasma-wave2-campaign-config.json.
- Check CI logs for any workflow that ran npm install on or after June 4, 2026, 02:46 UTC and resolved any affected package version.
- On developer workstations, check for tmp.0987654321.lock, files matching /tmp/p*.js, and Bun binaries in /tmp/b-* directories.
- Search GitHub organization activity for commits containing IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwner.
- Audit ~/.claude/settings.json for unexpected SessionStart entries on every developer machine that could have installed an affected package.
- Check .vscode/tasks.json in all project directories for unexpected folderOpen tasks.
- Run SBOM analysis across container images built after June 4, 2026, for affected package versions.
Remediation Guidance
Immediate Actions
- Set npm config set ignore-scripts true on all CI runners. This blocks preinstall/postinstall lifecycle hooks. See the note below before deploying globally — it does not fully address binding.gyp delivery in all environments.
- Pin all lockfiles to versions prior to June 4, 2026, for affected packages. Remove compromised versions from CI runner package caches and private registry proxies.
- If any affected version was installed: rotate all of the following on every environment that ran the install: GitHub PATs and fine-grained tokens, npm publish tokens, AWS access keys, GCP service account keys, Azure service principal credentials, HashiCorp Vault tokens, Kubernetes service account tokens, SSH private keys, Docker registry credentials.
- Manually remove persistence artifacts from developer workstations: delete unexpected SessionStart hooks from ~/.claude/settings.json and unexpected folderOpen tasks from .vscode/tasks.json in all project directories. Remove tmp.0987654321.lock and /tmp/b-* Bun directories.
- Revoke and audit GitHub Actions OIDC Trusted Publishing bindings for any packages hosted in repositories that may have been reached by the worm. Do not re-establish federation until the publish chain is confirmed clean.
IMPORTANT — The limits of –ignore-scripts: npm config set ignore-scripts true reliably blocks scripts.preinstall and scripts.postinstall. It does not universally prevent node-gyp in environments with legitimate native addons. The stronger control is a private registry proxy with a binding.gyp inspection step and an allow-list of packages permitted to invoke node-gyp. This addresses both Wave 1 and Wave 2 delivery mechanisms in a single control.
Mitigations if Lockfile Pinning Is Delayed
- Deploy network egress controls on CI runners, restricting outbound connections during npm install to registry endpoints only.
- Add npm package cooldown enforcement via a private registry proxy: newly published versions require a review window before being served to pipelines.
- Use StepSecurity Harden-Runner in audit mode to capture and alert on unexpected runtime processes and network activity during builds.
- Monitor for the firedalazer commit trigger in repositories the threat actor may have access to. Stage 5 dropper logic is present in the payload but currently dormant.
MITRE ATT&CK Mapping
| Technique | ID | Application |
| Supply Chain Compromise: Software Supply Chain | T1195.002 | Backdoored npm packages published to registry |
| Command and Scripting Interpreter: JavaScript | T1059.007 | Payload execution via node-gyp / binding.gyp and Bun runtime |
| Obfuscated Files or Information | T1027 | Four-layer obfuscation: ROT-21, AES-128-GCM, obfuscator.io, B5 cipher |
| Unsecured Credentials: Credentials In Files | T1552.001 | Sweep of ~/.aws, ~/.npmrc, ~/.kube/config, .env files |
| Unsecured Credentials: Credentials in Environment Variables | T1552.007 | GITHUB_TOKEN, AWS_ACCESS_KEY_ID, cloud credential env vars |
| OS Credential Dumping | T1003 | /proc/{pid}/mem read of Runner.Worker for masked secret extraction |
| Exfiltration Over C2 Channel | T1041 | AES-256-GCM encrypted HTTPS POST to attacker endpoint |
| Exfiltration to Code Repository | T1567.001 | GitHub Contents API fallback exfiltration channel |
| Event Triggered Execution | T1546 | Claude Code SessionStart and VS Code folderOpen persistence |
| Valid Accounts: Cloud Accounts | T1078.004 | bypass_2fa npm publish with harvested tokens for worm propagation |
Phoenix Security Platform Recommendations
The zero-CVE gap is not a theoretical concern for this campaign. All 57 compromised packages were published without triggering any CVE, GHSA, or OSV assignment. Teams relying on scanner workflows that gate on vulnerability database lookups had no signal during the active exposure window.
Phoenix Security’s malware intelligence platform at phxintel.security/malware.html detected Miasma packages through behavioral signal analysis within minutes of publication. CS-002 (install-hook-abuse) fires on both lifecycle-script and binding.gyp delivery because it analyzes execution triggers broadly rather than matching a specific package.json field.
Reachability analysis identifies which build environments actually executed an affected package’s install hook versus environments that listed the package as a dependency but installed from a pre-compromise cache. When scoping credential rotation, that distinction is operationally significant. Rotating credentials for 300 CI runners when 30 actually ran the payload wastes incident response time; missing any of those 30 leaves access open.
Remediation campaigns track the multi-step response across engineering teams: lockfile updates per repository, credential rotation completion per environment, persistence artifact cleanup per developer machine, OIDC rebinding confirmation per package, and container image rebuilds per registry. Without that tracking, teams finish the easy parts and lose visibility on the tail.
Attack surface management surfaces which pipelines and build environments pull from the affected namespaces, giving the security team a complete organizational exposure map rather than waiting for individual teams to self-report.
Campaign config, IOC scanner, and CISO brief for MIASMA_WAVE2_BINDINGYP_2026 are available at phxintel.security/package.html.
Download Phoenix Security campaign config.
Protect yourself with the latest threat intelligence, get access to PHOENIX BLUE Today
External References
- Socket Security — Miasma Supply Chain Attack Is Back on npm, over ~600,000 Monthly Downloads Affected (Moshe Siman Tov Bustan, Nir Zadok, June 4, 2026) — primary Wave 2 technical source
- Phoenix Security — MIASMA_WAVE1_REDHAT_2026 campaign analysis
- StepSecurity — Malware in @redhat-cloud-services npm Packages: Runtime Analysis (June 1, 2026)
- Phoenix Security — Mini Shai-Hulud / TeamPCP: TanStack and Mistral Campaign (May 2026)
- Phoenix Security — Sha1-Hulud reverse engineering and persistence IOCs
- Phoenix Security Malware Intelligence Platform
- Phoenix Security Campaign IOC Tracker
- Phoenix Security Open-Source npm Scanner
- StepSecurity disclosure — RedHatInsights/frontend-components Issue #2329
- StepSecurity disclosure — RedHatInsights/javascript-clients Issue #492