Supply chain attackers are getting more creative, and the latest threat is proof of that. A malware campaign known as Miasma has been caught hiding inside widely used npm packages, using a clever mix of tools and techniques to stay hidden while stealing sensitive developer credentials.
The attack involves packages tied to the LeoPlatform and RStreams ecosystems, which are used in data pipeline and cloud integration workflows.
Malicious versions of over 20 npm packages were published within a tight window on June 24, 2026, catching many developers off guard.
The scope of the attack is wider than it first appears, with additional infected packages published under a separate npm user account named llxlr.
Researchers at Socket.dev said in a report shared with Cyber Security News (CSN) that this campaign is part of a broader threat cluster also connected to related malware families called Mini Shai-Hulud and Hades.
The team has been tracking the family across multiple waves, noting that its techniques grow more layered and harder to detect with each new release.
What makes this wave particularly concerning is how far the damage can spread. The malware does not just sit inside an infected package.
Once it runs, it hunts for credentials, tokens, configuration files, and AI coding tool settings, then uses what it finds to poison other repositories and developer workflows.

The campaign also expands beyond npm. Socket researchers found the same payload family inside a Go module linked to the Verana Blockchain project, showing that the attackers are not limiting themselves to a single package ecosystem.
This confirms a troubling shift where threat actors are moving across package managers by targeting the workflows and tools developers rely on every day.
Miasma Malware Uses binding.gyp and Bun
The infection begins at the moment a developer installs a package. Instead of using a visible install script in package.json, the attackers added a file called binding.gyp to each malicious package.
When npm sees this file, it automatically runs node-gyp, a native build tool. The attackers exploit this behavior to trigger code execution without raising the red flags that a traditional install script would.
Once triggered, the malicious index.js file springs into action. It is a large, heavily scrambled single-line JavaScript loader that uses a Caesar-style letter shift and AES-GCM encryption to hide its real purpose.
When decoded, it delivers a final payload built to run through Bun, a fast JavaScript runtime. If Bun is not already installed on the machine, the malware downloads and installs it.
Many security tools do not watch Bun execution the same way they monitor Node.js, which helps the malware avoid detection.
Stealing Credentials Across Developer Environments
The payload targets a wide range of sensitive data. It collects environment files, npm and PyPI tokens, GitHub tokens, Slack and Twilio tokens, SSH keys, Kubernetes configs, AWS and Azure credentials, Docker authentication files, CI secrets, and settings tied to AI coding assistants like Claude, Cursor, and Gemini.
The malware also checks for popular security tools like CrowdStrike and SentinelOne, and includes a Russian locale guard that stops execution on Russian-language systems.
GitHub Actions is a key target, as the malware hunts for workflows that publish packages or hold registry tokens, pulling secrets from the runner environment and using GitHub’s own API to exfiltrate stolen data.
A recurring fake workflow named “Run Copilot” is designed to blend in with normal AI-assisted development activity while quietly uploading stolen secrets as artifacts.
Teams affected by this campaign should treat any environment that installed an affected package as fully compromised.
Rotate all secrets immediately from a clean machine, not from the potentially infected host. Rebuild from a known-good lockfile and audit repositories for injected files such as .github/setup.js, _index.js, orphan branches, and unexpected Bun usage in GitHub Actions runs.
Developers should also pin GitHub Actions to full-length commit hashes rather than mutable version tags to prevent tag-based redirection attacks going forward.
Indicators of Compromise (IoCs):-
| Type | Indicator | Description |
|---|---|---|
| SHA-256 | 32d1bc728d8e504952083a6adc488c309a401c7df4dc8f47b382ce32e4aebe21 | Confirmed LeoPlatform/RStreams set — binding.gyp |
| SHA-256 | 57ba86f6f0caaa580c1dccdf4ed7873d1470e5ea2f8e9ca7a989dc04899f13c0 | leo-logger@1.0.8 — index.js |
| SHA-256 | 4a0aa78757958683155a7b9289427fb829abcad1bf5ee6399eb73e8409b0bc11 | leo-logger@1.0.8 — package.json |
| SHA-256 | 026588d39b7c650b5c0dfbba6c6fcc0e7ec8e3b72ba8639012e7f71c708f2c3b | leo-sdk@6.0.19 — index.js |
| SHA-256 | df9ea0c71574e11c93141ad2f018a63a5375cd6d69ca2f744732ad7814170657 | leo-auth@4.0.6 — index.js |
| SHA-256 | 1a3b9ed0b377f56f49b9a703612cf45e86ab7d100587e1e7a476d809fe337a8c | leo-aws@2.0.4 — index.js |
| SHA-256 | f565988f281bf77bcad26ea7f543617e53da4b62f5df63d4f7a89bae1729cf81 | leo-sdk@6.0.19 — npm tarball |
| SHA-256 | a934a5bcf692b9d01e8129bf264be23809dfee464df471d75a9f3fa1bcede343 | leo-auth@4.0.6 — npm tarball |
| SHA-256 | f7c47be306351ffacd46584d2067f7be676dbfe17cd89ab4880632decfe18f3d | leo-aws@2.0.4 — npm tarball |
| SHA-256 | 3da2ca129c9920d9acd2e3477aee8f46b5a5f0e9537ad6e7b6ab1df1007adad1 | leo-cli@3.0.3 — npm tarball |
| SHA-256 | b3e217f4354e8a4383038b99b0bcaeaff191a79df58e7a1f2355a79aac2faf13 | verana-blockchain-v0.10.1-dev.20.zip (Go module) |
| SHA-256 | 15b415ae41df72acf1f7e9e67569531d41dee62d089d34b4c0fab0c7fe5cc14f | .claude/index.js (Go repo artifact) |
| SHA-256 | 6cb3fc3650355973b8a1ed86619a3f412fb0700f29c1c3a736cada4c2c76a9f7 | .claude/setup.mjs and .vscode/setup.mjs |
| SHA-256 | 6a861a479f45fe53f067091414332248bc027ffc396116811d12e57a6ff71250 | .claude/settings.json |
| SHA-256 | 927387d0cfac1118df4b383decc2ea6ba49c9d2f98b47098bcbcba1efc026e1f | .vscode/tasks.json |
| SHA-256 | 1a0e1daeaea87cab5610a3cc2aa72e7c6f1abfe55959a156368bcfa6585fa6ce | Decoded first-stage JavaScript |
| SHA-256 | ceff7c51d70832c3ec8dd2744b606a23b3c924ef664ae23439b9b742ea154108 | Decrypted Bun bootstrap payload |
| SHA-256 | 9f93d77d32833a515bc406c46da477142bb1ac2babeecb6aa42f98669a6db015 | Decrypted main Miasma payload |
| File Name | binding.gyp | Added to packages that previously did not require native build behavior |
| File Name | index.js | Replaced with large single-line obfuscated payload |
| File Name | .github/setup.js | Injected payload file in poisoned repositories |
| File Name | _index.js | Secondary payload file found in GitHub repositories |
| File Name | .claude/setup.mjs | Bun launcher script in poisoned Go source repo |
| File Name | .vscode/tasks.json | VS Code folder-open task triggering malware execution |
| File Name | .claude/settings.json | Claude AI agent hook for persistence |
| File Name | .cursor/rules/setup.mdc | Cursor IDE hook for persistence |
| Campaign String | RevokeAndItGoesKaboom | Operator dead-drop token in GitHub commits |
| Campaign String | Alright Lets See If This Works | Campaign marker string found across compromises |
| Campaign String | TheBeautifulSandsOfTime | Campaign marker string |
| Campaign String | thebeautifulmarchoftime | Campaign marker string |
| Campaign String | thebeautifulsnadsoftime | Campaign marker string |
| Package | leo-logger@1.0.8 | Malicious LeoPlatform npm package |
| Package | leo-sdk@6.0.19 | Malicious LeoPlatform npm package |
| Package | leo-auth@4.0.6 | Malicious LeoPlatform npm package |
| Package | leo-aws@2.0.4 | Malicious LeoPlatform npm package |
| Package | leo-cli@3.0.3 | Malicious LeoPlatform npm package |
| Package | hexo-deployer-wrangler@1.0.4 | Malicious npm package published by llxlr |
| Package | hexo-shoka-swiper@0.1.10 | Malicious npm package published by llxlr |
| Package | prism-silq@1.0.1 | Malicious npm package published by llxlr |
Note: IP addresses and domains are intentionally defanged (e.g., [.]) to prevent accidental resolution or hyperlinking. Re-fang only within controlled threat intelligence platforms such as MISP, VirusTotal, or your SIEM.