Four packages in the widely-used @asyncapi npm namespace — @asyncapi/generator, @asyncapi/generator-helpers, @asyncapi/generator-components, and @asyncapi/specs — were trojanized on July 14, 2026, in an attack that combined a classic GitHub Actions “pwn request” with a new, deliberately non-worming build of the Miasma malware family. Combined weekly downloads across the affected packages run into the low millions.

What happened

The root cause is a misconfigured pull_request_target workflow in the asyncapi/generator repository: the trigger runs with the base branch’s elevated permissions, but the job checked out and executed code from the incoming pull request itself — the textbook “pwn request” pattern GitHub and multiple researchers (most recently Wiz and Chainguard) have warned about for years. An attacker opened a pull request that abused this to exfiltrate a privileged GitHub personal access token belonging to asyncapi-bot, a service account with organization-wide publish rights.

With that token, the attacker pushed a malicious commit directly to the next branch at 06:58 UTC on July 14. That push triggered the repository’s automated release workflow, which built and published three trojanized packages to npm at 07:10 UTC; two more compromised versions followed shortly after, bringing the total to five malicious releases across the four packages.

Technical details

Unlike a typical install-script attack, this payload executes on import/require, not npm install — so simply running --ignore-scripts does not protect against it. The code injected into the packages is an obfuscated first-stage loader that reaches out to IPFS to fetch an encrypted second stage (CID QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9), an 8.25 MB blob that decrypts to a 3.09 MB bundled Node.js application researchers have identified as Miasma v3 — the same malware lineage behind June’s Shai-Hulud-style worm that hit @redhat-cloud-services packages. Obfuscation layers HKDF-SHA256 key derivation, AES-256-GCM encryption, and a printable-ASCII ROT transform on top of the payload and its configuration.

The notable difference from the June campaign: this deployment’s baked-in configuration sets recon:false and disables the npm, PyPI, RubyGems, and Cargo self-propagation modules that made the earlier wave a worm. The codebase still contains that propagation logic along with an “AI-tool poisoning” module and a metamorphic self-mutation routine, but none of it fires here — the operators, running an operation tagged miasma-train-p1, chose a quieter footprint: persistence, encrypted command-and-control, arbitrary shell execution, and remote payload replacement, prioritizing stealthy long-term access over rapid spread. Active credential-theft targets include saved passwords and cookies from Chrome, Brave, Firefox, and Edge; SSH keys; npm and GitHub tokens; AWS credentials; macOS Keychain items; and cryptocurrency wallets.

Impact

Any project that installed the affected @asyncapi packages between the July 14 07:10 UTC publish and pull from the registry is potentially compromised — and because the trigger is import/require, transitive dependents that merely bundled the code without running it directly are still at risk once that code executes anywhere in the build or runtime path. CI runners and developer workstations that pulled the packages should be treated as having live C2 connectivity until proven otherwise; the RAT’s remote-payload-replacement capability means the operators can push new capabilities into an already-compromised host at will.

Mitigation

Audit lockfiles, npm caches, and container images for @asyncapi/generator 3.3.1, @asyncapi/generator-helpers 1.1.1, @asyncapi/generator-components 0.7.1, and @asyncapi/specs 6.11.2 / 6.11.2-alpha.1; pin to a version published before July 14 or the maintainers’ subsequent clean release. Because execution happens at import time, --ignore-scripts will not help — you need to actually remove the bad versions from every install path, including build caches and previously-built images. Rotate GitHub tokens, npm publish tokens, AWS credentials, SSH keys, browser-saved credentials, and any crypto wallet material reachable from a host that loaded the package. Isolate and rebuild affected CI runners rather than trusting in-place cleanup, given the persistence and C2 capabilities involved.

For maintainers generally: never combine pull_request_target with a checkout of the PR’s own head ref — use the pull_request event with a read-only GITHUB_TOKEN for untrusted code, and reserve any privileged token for a separate, PR-independent workflow. Replace long-lived bot PATs with short-lived OIDC-based publishing wherever the registry supports it. AsyncAPI has since shipped workflow hardening in generator PR #2092.

Sources