StepSecurity Details Miasma Worm's binding.gyp Attack Across 57 npm Packages

· Original article ↗

Summary

StepSecurity reports that Miasma compromised 57 npm packages across 286+ versions using binding.gyp to execute during installs and steal CI/CD credentials. Controlled analysis observed runner-memory scraping and GitHub-based exfiltration.

Key points

  • StepSecurity reports a June 3 campaign affecting 57 npm packages across 286+ malicious versions in under two hours, including @vapi-ai/server-sdk and ai-sdk-ollama.
  • A 157-byte binding.gyp file triggers node-gyp and gyp command substitution to run a root-level payload during npm install, without package.json lifecycle scripts.
  • In a controlled GitHub Actions run, process and network telemetry showed a Bun download, gh auth token access, sudo-assisted Runner.Worker memory reads, and authenticated GitHub API uploads.
  • The payload targets CI/CD and cloud credentials; StepSecurity traced encrypted credential uploads to repositories created under the GitHub account liuende501.
  • StepSecurity's decoded-payload analysis indicates the malware can inject setup and configuration files for Claude Code, Cursor, Gemini, and VS Code into repositories accessible with stolen tokens.
  • The decoded worm logic indicates propagation across npm, RubyGems, and GitHub, with capabilities to forge Sigstore signing and SLSA provenance for republished packages.
  • The article recommends checking dependencies, CI logs, repositories, and credentials; StepSecurity says Harden-Runner terminated a test workflow after detecting anomalous behavior.

Article Details

Attack Vectors
  • Compromised npm packages use a 157-byte binding.gyp file and gyp command substitution to execute node index.js during npm install without declared preinstall or postinstall scripts.
  • The payload uses ROT-encoded JavaScript, AES-128-GCM-encrypted stages, and obfuscation before downloading Bun and launching the main payload.
  • The malware steals CI/CD credentials, including GitHub tokens, and reads GitHub Actions secrets from Runner.Worker process memory after invoking sudo python3.
  • Stolen credentials are used to publish infected packages across npm and RubyGems and to commit AI-assistant configuration backdoors to accessible repositories.
  • The malware exfiltrates encrypted credential data to attacker-created GitHub repositories and uses GitHub commit searches as a C2 beacon and token-validation mechanism.
Defensive Notes
  • If an affected package version was installed, treat the system as compromised; revoke and rotate accessible credentials, including npm, GitHub, cloud, Vault, RubyGems, SSH, and CI/CD tokens.
  • Inspect accessible repositories for unexpected AI-assistant configuration files and commits, including .claude/setup.mjs, .claude/settings.json, .cursor/rules/setup.mdc, .gemini/settings.json, .vscode/tasks.json, .vscode/setup.mjs, and .github/setup.js.
  • Review CI logs for unexpected node-gyp rebuilds, Bun downloads, curl or unzip child processes, runner-memory reads, new repositories, and unauthorized package publishes.
  • Block automatic node-gyp builds where possible, use npm install --ignore-scripts for lifecycle scripts, and pin packages with integrity hashes.
  • Use a package-registry cooldown period, tightly scope CI permissions, and flag oversized root-level index.js files that are not the declared package entry point.

Indicators of compromise

TypeIndicatorContext
SHA256288f26c2eadcb1a7923fe376d16f5404216cce15d9fc162a4a78574dc7df399aSHA-256 of the compromised [email protected] package tarball.
SHA2565926b86b642e00672252953eb30d8f75cfb7797fe3118bd6fa2cfbee92905d61SHA-256 of the obfuscated malicious root index.js from [email protected].
SHA25682d83274680df928fdda296a348e01802f595e412308c399565c320df444052aSHA-256 of the malicious index.js in @vapi-ai/[email protected].
SHA256ceff7c51d70832c3ec8dd2744b606a23b3c924ef664ae23439b9b742ea154108SHA-256 of the decrypted Bun loader used by the malware.
SHA256da39146ef451d1b174a24d00b1e2a45cd38d54e849737f8f35333dcb22175707SHA-256 of the decrypted Miasma main payload.
SHA256e3dbe63aded45278f49c4746ab938ed9472b36def79b43e2dd2d7eff014481d1SHA-256 of the malicious index.js in @vapi-ai/[email protected].
SHA256ef641e956f91d501b748085996303c96a64d67f63bfeef0dda175e5aa19cca90SHA-256 of the malicious binding.gyp install-hook file found in compromised packages.
URLhxxps[:]//api[.]github[.]com/repos/liuende501/nemean-hydra-34343/contents/results/results-1780551069887-0.jsonSpecific GitHub API resource used to upload an encrypted file of stolen credentials to an attacker-created repository.
URLhxxps[:]//api[.]github[.]com/search/commits?q=IfYouInvalidateThisTokenItWillNukeTheComputerOfTheOwnerGitHub commit-search URL used by the malware to validate its stolen token.
URLhxxps[:]//api[.]github[.]com/search/commits?q=thebeautifulmarchoftimeGitHub commit-search URL used by the malware as a C2 beacon.

MITRE ATT&CK

T1003.007 · Proc FilesystemThe malware reads /proc/2771/mem to extract GitHub Actions secrets from Runner.Worker memory.T1027 · Obfuscated Files or InformationThe payload uses ROT-encoded character data, encrypted stages, and obfuscator.io-obfuscated JavaScript.T1059.004 · Unix ShellThe gyp command substitution executes a shell command during installation; the payload also invokes curl and unzip.T1059.006 · PythonThe malware invokes sudo python3 to read the Runner.Worker process memory.T1059.007 · JavaScriptThe install trigger runs node index.js, and the downloaded Bun runtime executes the JavaScript payload.T1102.002 · Bidirectional CommunicationThe malware uses GitHub commit-search requests for C2 beaconing and token validation.T1105 · Ingress Tool TransferThe loader downloads and extracts the Bun runtime before launching the main payload.T1140 · Deobfuscate/Decode Files or InformationThe malware decodes the ROT-transformed content and decrypts AES-128-GCM blobs to recover its loader and main payload.T1195.002 · Compromise Software Supply ChainThe attacker published compromised npm package versions containing a binding.gyp trigger and malicious payload.T1528 · Steal Application Access TokenThe malware calls gh auth token to steal the GitHub CLI token and uses stolen tokens for API access.T1548.003 · Sudo and Sudo CachingThe malware invokes sudo python3 before reading Runner.Worker memory.T1552.005 · Cloud Instance Metadata APIThe malware attempts to retrieve credentials from AWS and Azure instance metadata endpoints.T1567.001 · Exfiltration to Code RepositoryThe malware uploads encrypted stolen credentials to results files in attacker-created GitHub repositories.

Malware

Vendors

Products

Tools

Related Articles