Skip to content

Back to the catalog

AsyncAPI npm packages backdoored via GitHub Actions
aikido.devwriteup

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.

TL;DR Attacker exploited an unpatched pull_request_target flaw in AsyncAPI's GitHub Actions to steal an npm token and backdoor 5 packages (2.9M weekly downloads) with an IPFS-hosted remote-shell implant.
Document

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.js at the three drop paths above and for the ~/.config/.miasma/ and miasma-monitor artifacts on any host that resolved these packages.
  • Block/alert on outbound fetches to ipfs.io for the two CIDs and to rentry[.]co (the token dead-drop used during initial access).
  • The theft used an unmerged pull_request_target fix (PR #2092, open ~2 months). Audit your own repos for pull_request_target workflows 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