
AsyncAPI npm packages backdoored via GitHub Actions
Aikido Security details how five @asyncapi npm packages (specs, generator, generator-helpers, generator-components), combined ~2.9M weekly downloads, were backdoored after an attacker exploited an unmerged pull_request_target GitHub Actions vulnerability in asyncapi/generator to steal the npm publish token via 37 flooded PRs. The injected runtime code spawns a detached Node process that downloads an encrypted stage-2 loader from IPFS, decrypts it via HKDF/AES-256-GCM, and drops a persistent remote-shell implant self-identified as 'M-RED-TEAM v6.4' with Miasma-branded artifacts, though credential harvesting and self-propagation are disabled in this build. The post includes full technical detail on the exfiltration flow, IOC strings, IPFS CIDs, and inconclusive attribution linking it to the prior Miasma toolkit and prt-scan campaign.
What it is
Five trojanized @asyncapi npm releases published 2026-07-14: @asyncapi/specs@6.11.2, @asyncapi/specs@6.11.2-alpha.1, @asyncapi/generator@3.3.1, @asyncapi/generator-helpers@1.1.1, and @asyncapi/generator-components@0.7.1. The summary names the campaign; this page gives the exact versions, file locations, and IOCs needed to detect and scope exposure.
How it works
The malicious loader is not in an npm lifecycle hook — it is prepended to modules that run during normal use (the specs entry point, a generator validator, a helper utility, a components error-handling module). A plain require() triggers it. The code spawns node -e '<obfuscated downloader>' as a detached process (detached: true, child.unref()), so the parent exits and download continues in the background. The downloader writes the stage-2 loader to sync.js in a per-user data directory, then runs it.
Drop paths by OS:
- macOS:
~/Library/Application Support/NodeJS/sync.js - Windows:
%LOCALAPPDATA%\NodeJS\sync.js - Linux:
~/.local/share/NodeJS/sync.js
IPFS CIDs (fetched as stage 2):
- specs branch:
Qmet4fhsAaWMBUxNDfREHwgiyDeSWy4YSYs9wiKUW5jGyf - generator family:
QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9
Other on-host IOCs: identity/lock files under ~/.config/.miasma/, persistence artifacts named miasma-monitor, spawn certs formatted miasma-spawn-cert-v1.
Preconditions / Affected
Any environment that installed one of the five versions above and imported the package. Because trigger is on module load, CI runners, dev machines, and build servers that merely require() the package are hit — not just those running a postinstall. Combined ~2.9M weekly downloads, with @asyncapi/specs at ~2.7M.
What to do
- Search lockfiles/installed trees for the five exact versions listed; pin to a known-good prior release.
- Hunt for
sync.jsat the three drop paths above and for the~/.config/.miasma/andmiasma-monitorartifacts on any host that resolved these packages. - Block/alert on outbound fetches to
ipfs.iofor the two CIDs and torentry[.]co(the token dead-drop used during initial access). - The theft used an unmerged
pull_request_targetfix (PR #2092, open ~2 months). Audit your own repos forpull_request_targetworkflows that check out and run external PR code with secrets in scope.
Caveats
Credential harvesting and self-propagation exist in the code but are disabled in this build — the remote shell is still fully functional for arbitrary command execution and data collection. Attribution is unresolved: prt-scan initial access, self-labeled M-RED-TEAM v6.4, and Miasma branding overlap but the page makes no definitive call and notes the payload differs from prior Miasma builds (Node/secp256k1/AES-GCM here vs. Bun/RSA/AES-CBC before).
Organisations named here
- Miasma toolkit
- M-RED-TEAM v6.4
- PR #2092
- PR #2155
- pull_request_target vulnerability
Technologies named here
- npm
- GitHub Actions
- Node.js
- IPFS
Threat actors named here
- prt-scan campaign
Related in Supply Chain


