Between June 24 and June 26 several researchers reported a new variant in the Miasma lineage spreading across npm, with open-source malware tracking from OpenSourceMalware confirming the package set and affected versions. The npm maintainer account czirker, which owns the LeoPlatform (leo-* and rstreams-*) package family, was compromised: every package under the account was republished with a malicious index.js. There are 23 affected packages with roughly 52,640 combined monthly downloads, and at the time of their writing 338 GitHub repositories already held credential dumps committed by infected machines.
This in preview to other opaque and speculative work from potentially Team PCP’s previous exfiltration
![]() | ![]() |
The execution mechanism is the binding.gyp pivot that defined Miasma Wave 2, now paired with a Bun runtime swap. The malicious index.js is referenced by a planted binding.gyp whose sources field abuses node-gyp’s <!(…) shell-exec syntax to run node index.js > /dev/null 2>&1 at install time. The obfuscated loader decrypts an AES-128-GCM blob, downloads the legitimate Bun runtime from the official oven-sh/bun GitHub release, writes the decrypted payload to /tmp/p<random>.js, and executes it under Bun rather than Node. Running the implant under Bun is the deliberate part: it sidesteps EDR, SCA, and runtime monitoring that hook into the Node process model. The payload then sweeps GitHub, npm, AWS, GCP, and Azure credentials plus local environment data and exfiltrates through the GitHub API.

Two details set this variant apart from the TeamPCP-attributed Miasma waves. OX Security found new public encryption keys embedded in the loader, which points to a different operator rather than the established Miasma crew, and the dropped second stage decodes back to a separate variant labeled “Hades * The End for the Damned” that carries the same key material seen in this Miasma build. The exfiltration marker also changed: instead of the name: description commit format used previously, infected machines commit credential dumps under the string “Alright Lets See If This Works”. No CVE, GHSA, or OSV record exists for any affected version, and OX Security notes the packages were still live on npm when they published.
TL;DR for Engineering Teams
| What it is | New variant in the Miasma/Hades lineage (Shai-Hulud derivative). The npm account czirker was compromised and its 23 LeoPlatform packages republished with a credential-stealing index.js. ~52,640 monthly downloads in scope. No CVE. |
| Where it bites | Any npm install resolving an affected leo-*, rstreams-*, serverless-*, or solo-nav version published on June 25, 2026. A planted binding.gyp fires node-gyp at install time, before application code runs. CI runners and developer workstations both affected. |
| Why it matters | The payload runs under Bun, not Node, to evade Node-focused EDR/SCA/runtime monitoring. It steals GitHub, npm, AWS, GCP, and Azure credentials and exfiltrates via the GitHub API. 338 repositories already hold stolen-credential commits. Packages were still live on npm at disclosure. |
| Patch status | No clean successor versions confirmed. Pin lockfiles to versions prior to the June 25, 2026 republish. Do not run npm install or npm update against the affected packages until integrity is confirmed. |
| Immediate action | Search all lockfiles for the affected versions below. If any match: rotate GitHub tokens, npm tokens, and AWS/GCP/Azure credentials on every host that ran the install, enable 2FA, and downgrade to a safe version. Set npm install –ignore-scripts on CI runners as a partial control. |
Contents
ToggleVulnerability Overview
| Campaign | MIASMA_HADES_LEOPLATFORM_2026 |
| Malware Family | Miasma (Shai-Hulud variant lineage); dropped second stage maps to the Hades variant |
| Vendor | LeoPlatform (npm publisher account czirker) |
| Product | LeoPlatform / RStreams npm package family |
| Vulnerability Type | Supply chain compromise; install-time code execution; credential theft |
| CWE | CWE-506 (Embedded Malicious Code); CWE-829 (Inclusion of Functionality from Untrusted Control Sphere); CWE-94 (Improper Control of Generation of Code) |
| CVSS | Not assigned |
| CVE | Not assigned |
| GHSA / OSV | Not assigned |
| Patch Available | No — remove and pin to prior version, rotate credentials |
| Active Exploitation | Confirmed — 338 infected GitHub repositories at disclosure |
| Account Compromise | ~4 hours before disclosure (June 25, 2026); first GitHub artifact Wed, 24 Jun 2026 09:33:24 -0700 |
| Packages Compromised | 23 |
| Monthly Downloads Affected | ~52,640 |
| Attribution | Unknown operator. New public keys diverge from TeamPCP/prior Miasma; OX Security assesses a new actor |
Technical Breakdown
Root Cause: Account Compromise Plus binding.gyp Execution
The entry condition is a maintainer account compromise, not a software flaw. OX Security assesses that czirker was compromised through leaked credentials or an npm token lifted by an infostealer, then used to republish every package the account owned with the malicious payload attached. There is no vulnerable code path in the original LeoPlatform packages. The trust relationship between npm and a verified publisher is what the attacker abused.
Execution rides on the same binding.gyp technique seen in Miasma Wave 2. node-gyp reads binding.gyp to compile native addons, and its sources field accepts the <!(…) syntax to run a shell command and capture its output. The planted binding.gyp puts a command in that field that runs node index.js > /dev/null 2>&1. When npm installs the package and invokes node-gyp, the command fires during what looks like a normal native build step, with output suppressed. Tooling that inspects package.json for suspicious preinstall or postinstall lifecycle hooks sees nothing, because there are no lifecycle hooks. The execution surface moved off the field defenders learned to watch.
The Bun runtime swap is the second layer of evasion. Rather than running the implant under the Node process that EDR and runtime monitoring already instrument, the loader downloads the legitimate Bun binary from the official oven-sh/bun GitHub release, drops the decrypted payload to /tmp/p<random>.js, and executes it under Bun. Security tooling tuned to the Node process model is far less likely to have visibility into a Bun process spawned from a temp directory.
Obfuscation and Loader Chain
The replaced index.js is a single line, char-code plus Caesar obfuscated. For leo-sdk, OX Security and OpenSourceMalware report the file is roughly 5.1 MB and the decrypted Bun payload is roughly 762 KB, bundled with javascript-obfuscator. The loader decrypts an embedded AES-128-GCM blob to recover the Bun downloader and the main implant. Visible function names in the decrypted payload (githubFetch, githubHeaders, githubJson) and string-table keywords (GITHUB, NPM, AWS, TOKEN, SECRET, Authorization) indicate credential and token theft with the GitHub API as at least one exfiltration channel.
The spreading mechanism reuses a GitHub search trick: the loader searches GitHub for a commit string firedalazer, which was committed roughly two weeks before disclosure and remained live. That commit, hosted on the compromised miaxxxxxx account, decodes to a raw GitHub URL on a second compromised account, l3v1cs, which serves the next stage. After further decoding, the dropped malware maps back to the Hades variant (“Hades * The End for the Damned”), which OX Security reports had 173 infected repositories and surfaced 15 to 16 days earlier. The Hades stage carries public keys that match the ones in this Miasma build, tying the two together.

Exploit Path
- Entry point. The attacker, holding the compromised czirker npm account, republishes all 23 LeoPlatform packages with a malicious index.js and a planted binding.gyp. A developer or CI runner executes npm install against any affected version. npm invokes node-gyp to process binding.gyp.
- Trigger. node-gyp evaluates the sources field, whose <!(…) shell-exec entry runs node index.js > /dev/null 2>&1. The obfuscated loader decrypts the AES-128-GCM blob, fetches the legitimate Bun runtime from the oven-sh/bun GitHub release, and writes the decrypted payload to /tmp/p<random>.js.
- Execution impact. The implant runs under Bun, outside Node-focused monitoring. It harvests GitHub tokens, npm tokens, AWS/GCP/Azure cloud credentials, and local environment data, then commits the stolen material to attacker-controlled GitHub repositories under the marker string “Alright Lets See If This Works”. The loader’s GitHub-search spreading logic pulls the Hades second stage from the l3v1cs account for continued propagation.
Campaign Timeline
| Date / Event | Activity |
| ~15–16 days before disclosure | Hades variant (“Hades * The End for the Damned”) surfaces; 173 infected repositories observed |
| ~2 weeks before disclosure | firedalazer spreading commit planted on the miaxxxxxx GitHub account; remains live |
| Wed, 24 Jun 2026 09:33:24 -0700 | First GitHub commit containing the “Alright Lets See If This Works” marker string |
| June 25, 2026 (~4 hours before disclosure) | czirker npm account compromised; all 23 LeoPlatform packages republished with the malicious payload |
| June 25, 2026 (disclosure) | OX Security publishes; 338 GitHub repositories already hold stolen-credential commits; packages still live on npm |
Affected Versions
All versions below were published under the compromised czirker account on June 25, 2026 and should be treated as malicious. Downgrade to the last release prior to the republish for each package. Monthly download figures are from the OpenSourceMalware / OX Security disclosure.
| Package | Compromised Version | Fixed Version | Monthly Downloads |
| leo-logger | 1.0.8 | prior release | 11,655 |
| leo-sdk | 6.0.19 | prior release | 5,530 |
| leo-aws | 2.0.4 | prior release | 5,160 |
| leo-config | 1.1.1 | prior release | 4,967 |
| leo-streams | 2.0.1 | prior release | 3,761 |
| serverless-leo | 3.0.14 | prior release | 3,625 |
| serverless-convention | 2.0.4 | prior release | 2,398 |
| leo-connector-elasticsearch | 2.0.6 | prior release | 2,014 |
| rstreams-metrics | 2.0.2 | prior release | 1,861 |
| leo-auth | 4.0.6 | prior release | 1,577 |
| leo-connector-mongo | 3.0.8 | prior release | 1,352 |
| leo-cache | 1.0.2 | prior release | 1,049 |
| leo-cli | 3.0.3 | prior release | 321 |
| leo-cron | 2.0.2 | prior release | 238 |
| leo-connector-redshift | 3.0.6 | prior release | 184 |
| leo-connector-mysql | 3.0.3 | prior release | 164 |
| leo-connector-oracle | 2.0.1 | prior release | 72 |
| rstreams-shard-util | 1.0.1 | prior release | 31 |
| leo-cdk-lib | 0.0.2 | prior release | 17 |
| solo-nav | 1.0.1 | prior release | 7 |
| leo-connector-common | 4.0.11-rc | prior release | — |
| leo-connector-postgres | 4.0.19-beta | prior release | — |
| leo-connector-entity-table | 3.0.22-rc | prior release | — |
Note: OX Security’s affected-package list enumerates 23 packages including three pre-release versions (leo-connector-common@4.0.11-rc, leo-connector-postgres@4.0.19-beta, leo-connector-entity-table@3.0.22-rc). The LinkedIn summary lists the 20 stable packages with download counts. Treat all 23 as in scope. Pin to the last clean version of each package and verify integrity before reinstalling.

Exposure Analysis
| Environment | Risk Level | Reason |
| CI/CD pipelines | Critical | binding.gyp fires node-gyp automatically on npm install; build-environment cloud credentials and npm/GitHub tokens are in scope; payload runs under Bun outside Node monitoring |
| Developer workstations | Critical | Local npm install triggers the same chain; GitHub, npm, and cloud credentials plus local environment data swept; stolen tokens enable further compromise |
| Cloud workloads | High | Harvested AWS/GCP/Azure credentials enable lateral movement and resource access beyond the build host |
| Container image builds | High | Any image build running npm install against an affected version executes the payload; credentials in the build context are exposed |
| With –ignore-scripts | Reduced, not eliminated | Blocks lifecycle hooks but does not universally prevent node-gyp where legitimate native addons are expected |
The download counts are modest relative to prior Miasma waves, but the credential sweep makes exposure disproportionate to install volume. A single compromised CI runner with an AWS access key, a GitHub PAT, and an npm publish token gives an attacker the material to move laterally and to republish backdoored packages elsewhere. The leo-aws, leo-connector-*, and serverless-leo packages sit specifically in data-pipeline and AWS-integrated workloads, where cloud credentials are most likely to be present in the install environment.
Real-World Impact
The 338 GitHub repositories holding stolen-credential commits at disclosure are the concrete evidence that this is not theoretical. Each of those commits is a set of credentials already in attacker hands. The exfiltration marker “Alright Lets See If This Works” is a reliable search string for hunting infected repositories across an organization’s GitHub footprint.
The Hades linkage matters for scoping. The dropped second stage decodes to a separate variant with its own 173-repository footprint observed two weeks earlier, and the shared public keys connect the two campaigns operationally. An organization that finds one marker should hunt for both, and should treat the firedalazer spreading commit and the l3v1cs / miaxxxxxx accounts as part of the same activity cluster.
Attribution is unsettled. OX Security assesses, based on the new public encryption keys, that this is likely a new operator rather than TeamPCP or the established Miasma crew. For defenders the attribution question is secondary to the practical reality: the technique stack (binding.gyp execution, Bun evasion, GitHub-native C2) is now being reused across operators, which means treating any one of these as a single-actor problem understates the exposure.
Detection Guidance
Host and Process Indicators
| Type | Indicator |
| Process | A Bun process executing /tmp/p<random>.js spawned from an npm install / node-gyp step |
| Process | node index.js invoked from within a node-gyp build rather than application code |
| File creation | /tmp/p<random>.js; staged Bun binary downloaded from oven-sh/bun GitHub releases |
| Suspicious file | A binding.gyp present in a leo-*, rstreams-*, serverless-*, or solo-nav package, none of which legitimately ship native addons |
| Oversized file | An index.js of several MB (e.g. ~5.1 MB for leo-sdk), single-line and obfuscated |
| GitHub artifact | Commits containing the marker string: Alright Lets See If This Works |
| GitHub artifact | Commits or repositories referencing firedalazer, or content served from l3v1cs / miaxxxxxx |
Network Indicators (during npm install)
| Indicator | Context |
| github[.]com/oven-sh/bun/releases/download/… | Bun runtime staging from the official GitHub release |
| api.github[.]com | Credential exfiltration and second-stage retrieval channel |
| raw[.]githubusercontent[.]com/l3v1cs/Html-Bootstrap-TinDog/… | Second-stage payload host (defanged) |
| AWS IMDS / GCP / Azure metadata endpoints | Cloud credential enumeration from the build host |
Scanner and Phoenix Malware Intelligence Detection
CVE-driven SCA produced nothing here, which is the structural point of the zero-CVE gap. Behavioral detection is the only surface that fires during the live window. Phoenix Security’s malware intelligence at phxintel.security/malware.html surfaces the relevant behavioral signals regardless of CVE assignment: install-hook abuse for the binding.gyp invocation, credential-harvesting on the indexed token-access patterns, and payload-download plus exfiltration on the network activity. As in prior Miasma waves, a low heuristic score does not mean low risk: the credential-stealing payload is identical across all affected packages regardless of how much of the obfuscated loader a static scanner indexes before runtime decryption.
Verification Steps for Teams
- Search every package-lock.json, yarn.lock, pnpm-lock.yaml, and npm-shrinkwrap.json across all repositories for the affected packages at the versions listed above.
- Check CI logs for any workflow that ran npm install on or after June 25, 2026 and resolved an affected version.
- On any host that may have installed an affected version, look for a Bun process executing /tmp/p<random>.js and for an oversized obfuscated index.js in the package directory.
- Search the GitHub organization for commits containing “Alright Lets See If This Works” and for any reference to firedalazer.
- Run SBOM analysis across container images built on or after June 25, 2026 for the affected package versions and their transitive inclusion.
Remediation Guidance
Immediate Actions
- Pin all lockfiles to the last release of each affected package published before June 25, 2026. Remove the compromised versions from CI runner caches and any private registry proxy. Do not run npm install or npm update against these packages until integrity is confirmed.
- If any affected version was installed on any host, rotate every credential reachable from that host: GitHub PATs and fine-grained tokens, npm publish tokens, AWS access keys, GCP service account keys, and Azure service principal credentials. Treat the credentials as compromised, not merely exposed.
- Enable 2FA on npm and GitHub accounts for all maintainers, and require it for publish operations, to reduce the account-takeover path that started this campaign.
- Set npm config set ignore-scripts true on CI runners as a partial control (see the tradeoff note below).
- Hunt GitHub for the “Alright Lets See If This Works” marker and remediate any repository found holding stolen credentials, including rotating everything those credentials protect.
Temporary Mitigations (if pinning is delayed)
- Block outbound access from CI runners to oven-sh/bun release download URLs and to raw.githubusercontent.com paths not on an allow-list, to interrupt the Bun staging and second-stage retrieval.
- Add a private registry proxy step that inspects packages for an unexpected binding.gyp and blocks install for packages on the affected list that have no legitimate native-addon requirement.
- Restrict CI runner egress to known-good endpoints so credential exfiltration to api.github.com from an unexpected process is denied or alerted.
Tradeoff Note
npm config set ignore-scripts true reliably blocks preinstall and postinstall lifecycle hooks, but it does not universally prevent node-gyp from running where legitimate native addons exist, which is the exact path this variant uses. The stronger, single control is a private registry proxy with a binding.gyp inspection and an allow-list of packages permitted to invoke node-gyp. That addresses both lifecycle-script and binding.gyp delivery at once.
Phoenix Security Recommendations
Phoenix Security correlates this campaign against your actual dependency graph and runtime, not against a CVE database that has nothing to match. Import the affected package and version list as a remediation campaign, and the platform identifies which repositories and workloads resolve an affected version, deduplicates findings across scanners into a single prioritized backlog, and assigns ownership to the team that controls each affected service.
Reachability and exposure context drive prioritization. A leo-aws or serverless-leo instance in a CI pipeline with live AWS credentials is a different priority than the same package pinned and unused in an archived repository. Phoenix attack surface management identifies which affected workloads sit in internet-exposed or credential-rich environments so the rotation and pinning effort goes to the highest-exposure hosts first. Remediation campaigns track each fix from assignment through verification, and the live IOC feed at phxintel.security keeps the marker strings, accounts, and URLs current as the Miasma/Hades cluster evolves.
External References
- OX Security — “‘Alright Lets See If This Works’: Shai-Hulud / Miasma / Hades Variant Spreads on npm,” Moshe Siman Tov Bustan, June 25, 2026.
- OpenSourceMalware — LeoPlatform Miasma cluster, affected packages and versions (lnkd.in/ghidBUqS).
- npm — compromised maintainer account: npmjs.com/~czirker.
- GitHub — infected accounts used in the spread: github.com/miaxxxxxx, github.com/l3v1cs.
- Phoenix Security — Miasma Wave 2 analysis (binding.gyp delivery and Bun execution): phoenix.security/resources/blogs/.
- Phoenix Security — live malware intelligence feed: phxintel.security/malware.html.
Kudos to OX Security (Moshe Siman Tov Bustan, with help from Kirk at derp.ca) for the discovery and analysis, and to OpenSourceMalware for the package and version tracking.

