Skip to content
feed: live
>_ 0dayNews
supply chain
● Breaking

Miasma loader shipped in 5 @asyncapi npm package versions

5 @asyncapi npm versions unpublished. Miasma loader ships 744 modules over six C2 channels. Attackers compromised the CI/CD pipeline, not npm tokens — treat as post-install compromise.

Miasma loader shipped in 5 @asyncapi npm package versions
Image: 0dayNews / 0dayNews Editorial · All rights reserved
airgap airgap · Published · 3 min read

Confirmed: four packages in the @asyncapi npm namespace — five versions total — shipped a multi-stage loader that pulled a botnet framework called Miasma onto any host that imported them. All five versions have been unpublished from npm. Confidence on affected versions and unpublish action: as-reported by OX Security, SafeDep, Socket, and StepSecurity. Confidence on the initial-access path (CI/CD, not credentials): as-reported; treat as high-confidence pending a maintainer post-mortem.

The five versions

Per the joint reporting relayed by The Hacker News:

  • @asyncapi/generator-helpers@1.1.1
  • @asyncapi/generator-components@0.7.1
  • @asyncapi/generator@3.3.1
  • @asyncapi/specs@6.11.2
  • @asyncapi/specs@6.11.2-alpha.1

All five have been pulled from the registry. If your lockfile pins one of these, treat any environment that resolved and executed it — CI runner, developer laptop, container build — as compromised until proven otherwise. The loader ran on require(), not on npm install, so simple install-time scanners missed it.

What the loader does

The write-ups describe three stages, each disclosed at the level of behavior, not weaponization:

  • Stage 1 — obfuscated JavaScript inside the module, triggered when the package is loaded via require().
  • Stage 2 — a hidden sync.js written to OS-specific paths, pulling an encrypted payload from an IPFS content-addressed URL.
  • Stage 3 — the Miasma framework: 744 modules, six independent command-and-control channels (HTTP, Nostr relays, IPFS, BitTorrent DHT, libp2p GossipSub P2P mesh, and Ethereum smart-contract reads).

Six C2s means no single takedown breaks callback. Nostr and Ethereum-read C2 in particular sit on infrastructure defenders don’t typically block at the perimeter.

Documented capabilities: credential and token theft; lateral movement across LAN; worm-like propagation across npm, PyPI, and Cargo registries; persistence via systemd, crontab, launchd, and Windows Registry autostart; sandbox and EDR evasion (CrowdStrike, SentinelOne, Microsoft Defender named in the reporting); and a dead-man switch that wipes the working directory if the stolen tokens get revoked. We are not publishing IOC hashes, C2 URIs, or the payload address — those live in the vendor reports linked below.

Not stolen tokens — CI/CD pipeline

Attribution on the initial-access side is what makes this one worth watching separately. One of the researchers, quoted in the reporting: “Both attacks are CI/CD pipeline compromises, not stolen npm tokens or malicious maintainers.” The push carried valid GitHub Actions OIDC provenance attestations — meaning the malicious versions were signed by the legitimate release workflow, exactly the way a benign release would be.

That’s the same class of failure as the Injective SDK OIDC-branch push last week and the jscrambler post-mortem from yesterday: provenance attestations verified who ran the workflow, not whether the workflow itself had been tampered with. npm’s allow-scripts: off default, rolled out in npm 12, does not help here — the code ran at require(), not install.

What to do

  • Search lockfiles now. Any of the five versions listed above in package-lock.json, pnpm-lock.yaml, or yarn.lock, on any host — developer, CI, container base image — is a lead. grep -r '@asyncapi/generator@3.3.1' . and equivalents for the other four.
  • Rotate credentials on any host that imported one. npm tokens, cloud tokens, SSH keys, session cookies. The dead-man switch punishes revocation, so isolate first, then rotate.
  • Pin to known-good. The unpublished versions are gone from the registry, but a stale internal mirror or a lockfile checked in before the takedown will still resolve them from cache.
  • Watch outbound to IPFS, Nostr relays, and libp2p peers from build fleets. Those are not normal for a build agent. If your egress policy allows them by default, tighten it.

Sources

More as the four vendors publish detailed IOCs and the AsyncAPI maintainers post a root-cause. Treat this as active — the loader is designed to survive takedown of any single channel.

Found this useful? Share it.