AsyncAPI npm org compromised — 4 packages / 5 versions ship Miasma botnet loader via GitHub Actions `pull_request_target` pwn request
On 2026-07-14 an attacker exploited a pull_request_target misconfiguration in asyncapi/generator to steal a highly-privileged GitHub PAT, then published five malicious @asyncapi/* releases through the project's own trusted GitHub Actions release pipeline — valid npm OIDC provenance and all. The payload fires on require(), spawns a detached Node process, fetches an 8.25 MB IPFS loader (Miasma), and installs a 3.09 MB implant with six independent C2 channels (HTTP, Nostr, IPFS, BitTorrent DHT, libp2p GossipSub, Ethereum smart contract). Combined weekly downloads: ~2.9M.
- Threat actor
- Miasma
- Detected by
- Socket · Datadog Security Labs · StepSecurity · Aikido · Wiz · OX Security · Chainguard · SafeDep
- Also known as
- AsyncAPI Miasma compromise · AsyncAPI pwn request compromise · M-Red-Team AsyncAPI
- Ecosystems
- npm
- Packages tracked
- 4
What happened
On 2026-07-14 at approximately 05:03 UTC an attacker (GitHub user elzotebo999, subsequently deleted and now displayed as "ghost") opened the first of 37 spam pull requests against asyncapi/generator. At 05:08 UTC the attacker authored malicious commit 47be388; at 05:11 UTC a pull_request_target-triggered Docs Preview (Netlify) workflow ran with the repository's privileged GITHUB_TOKEN and organization-scoped PAT in scope. By 05:17 UTC the workflow had exfiltrated the PAT to a Rentry paste. Between 05:40 and 07:05 UTC a series of malicious commits were force-pushed to the repository's next branch. At 07:10:42 UTC the project's legitimate release workflow triggered on the poisoned next branch and published the first malicious tarball — the compromise had, from PR-open to malicious-release-live, taken about two hours and seven minutes.
Package + version manifest
Exact publish timestamps confirmed against the public npm registry time map:
| Package | Malicious version | Publish (UTC) | Clean predecessor | |---|---|---|---| | @asyncapi/generator-helpers | 1.1.1 | 2026-07-14 07:10:42 | 1.1.0 | | @asyncapi/generator-components | 0.7.1 | 2026-07-14 07:10:44 | 0.7.0 | | @asyncapi/generator | 3.3.1 | 2026-07-14 07:10:48 | 3.3.0 | | @asyncapi/specs | 6.11.2-alpha.1 | 2026-07-14 08:06:20 | 6.11.1 | | @asyncapi/specs | 6.11.2 | 2026-07-14 08:30:09 | 6.11.1 |
@asyncapi/specs accounts for approximately 2.7M of the ~2.9M combined weekly downloads across the four packages. The alpha.1 publish is unusual for AsyncAPI's stable-release cadence and appears to be either a probe or a fallback for lockfiles pinned to alpha channels — the same malicious payload shipped in both alpha.1 and the stable 6.11.2.
Attack chain — pwn request against pull_request_target
Datadog Security Labs' reconstruction and StepSecurity's CI-side analysis both attribute the entry to a pull_request_target "pwn request" vulnerability in the Docs Preview (Netlify) workflow. The workflow was configured to check out the PR HEAD (attacker-controlled code) while running with the repository's privileged secrets in scope. PR #2155 — one of 37 spam PRs in the burst — modified files under apps/generator/docs/ in a way that caused the workflow to execute attacker-controlled JavaScript with the repository's GITHUB_TOKEN and a highly-privileged organization-scoped PAT accessible.
The attacker exfiltrated the stolen PAT to a Rentry paste URL and then used the PAT out-of-band to force-push malicious commits directly to the next branch (bypassing branch protection because the PAT had admin-level scope). When the project's legitimate release workflow triggered on that branch, it published tarballs derived from the attacker's code — with valid npm OIDC provenance attestations, because the release workflow itself is the trusted publisher. npm audit signatures PASSES on the malicious tarballs.
The payload — Miasma botnet loader
The malicious code is embedded in normal runtime modules (not lifecycle scripts) and executes on require() or import. On load it:
- Uses
child_process.spawnto launch a detachednode -eprocess (.unref()'d, hidden from installer process tree). - Fetches an encrypted 8.25 MB JavaScript loader from IPFS CID
QmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9, saves it locally assync.js. - Decrypts a 3.09 MB implant (744 bundled modules) using an attacker public key (
0432fa4ba871877d94081fe83323fa24dfa1491e9de8725cbab7b734de9e9be3b233ef6742fd6264437c9532223d687b05fa540b70af6a516b8539af84d0eeb48e— secp256k1). - Establishes six parallel C2 channels: HTTP to
85.137.53.71:8080/8081/8091, Nostr relay, IPFS-based command retrieval, BitTorrent DHT rendezvous, libp2p GossipSub P2P mesh, and Ethereum contract callbacks at0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710. - Harvests browser passwords/cookies (Chrome, Brave, Firefox, Edge), SSH keys, npm/GitHub tokens, AWS/GCP credentials, macOS Keychain, Slack/Discord/Telegram tokens, crypto wallets.
- Establishes persistence by writing malicious task definitions into
.vscode/tasks.jsonand.claude/settings.jsonin the victim's home directory — the implant re-launches whenever the developer next opens VS Code or Claude Code.
The payload family is the same Miasma botnet loader documented in Aikido's Miasma variant writeup and previously observed in the Miasma / redhat-cloud-services June cluster. The AsyncAPI variant is the largest-blast-radius Miasma delivery to date.
Remediation status
All five malicious versions have been unpublished from the public npm registry (not merely deprecated — the tarballs no longer resolve). The current dist-tag latest for each package points at the clean predecessor. However:
- Private registry mirrors (Verdaccio, Artifactory, Nexus, Cloudsmith) will keep serving the cached tarballs until an operator manually evicts them.
- Build images baked between 2026-07-14 07:10 UTC and the unpublish still contain the malicious code and remain live until re-baked.
- The AsyncAPI project has published an official incident report and a post-mortem committing to migrate away from
pull_request_targeton all publish-adjacent workflows.
Context — three high-profile GitHub-Actions supply-chain compromises in eight days
This is the third public npm supply chain incident in eight days rooted in GitHub Actions / repository-side compromise:
- 2026-07-08 —
@injectivelabs/sdk-ts17-package wallet-drain burst, delivered via maintainer GitHub account takeover. - 2026-07-11 — Jscrambler
jscrambler+ plugins, delivered via stolen npm publish token. - 2026-07-14 — this AsyncAPI Miasma delivery via
pull_request_targetpwn request.
The pattern is a shift away from typosquats toward compromise of legitimate high-download packages via CI/CD or maintainer-account weaknesses — an arc that Palo Alto Networks' npm threat landscape monitoring has been flagging since Q2 2026.
Affected packages (4)
- npm
@asyncapi/generator3.3.1 - npm
@asyncapi/generator-components0.7.1 - npm
@asyncapi/generator-helpers1.1.1 - npm
@asyncapi/specs6.11.2-alpha.16.11.2
Impact
- Any Node.js process that
require()d orimported@asyncapi/generator@3.3.1,@asyncapi/generator-components@0.7.1,@asyncapi/generator-helpers@1.1.1,@asyncapi/specs@6.11.2, or@asyncapi/specs@6.11.2-alpha.1during the exposure window (2026-07-14 07:10 UTC → unpublish, roughly 24–36 hours) must be treated as fully compromised — the payload runs at import time, not just install time, so--ignore-scriptsprovides zero mitigation - Massive transitive blast radius:
@asyncapi/specsalone carries ~2.7M weekly downloads and is a direct dependency of AsyncAPI CLI, Kong Insomnia, Postman workspaces, and many enterprise API-tooling stacks; combined weekly downloads across the four packages exceeds 2.9M. Any project that pulled the malicious version through a transitive AsyncAPI dependency inherited the full Miasma implant - The Miasma loader harvests: browser saved passwords and cookies (Chrome, Brave, Firefox, Edge), SSH keys, npm and GitHub tokens, AWS credentials, macOS Keychain, and cryptocurrency wallet data. Persistence is achieved through injection into
.vscode/tasks.jsonand.claude/settings.jsonon the victim's workstation — meaning the implant survives reboot AND continues to fire whenever the developer opens VS Code or Claude Code - The implant is a command framework with six independent C2 channels (HTTP, Nostr relay, IPFS, BitTorrent DHT, libp2p GossipSub P2P mesh, Ethereum smart contract callback at
0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710). Blocking any single egress channel does not neutralize the implant; six channels means single-egress firewalls will not stop C2 - The malicious versions were published through the AsyncAPI project's own legitimate GitHub Actions release workflow with valid npm OIDC provenance attestations — meaning
npm audit signaturesPASSES on these tarballs. Provenance-based trust checks that expect "if OIDC-signed then benign" will not flag these publishes - Reveals a class of
pull_request_targetGitHub Actions vulnerability the security community calls a "pwn request": a PR that touches a specific path (apps/generator/docs/) triggered aDocs Preview (Netlify)workflow running with the repository's privileged GITHUB_TOKEN and organization-scoped PAT in scope — the attacker chained a run of the workflow to exfiltrate the PAT to a Rentry paste and then used the PAT to force-push malicious commits to protected branches
What to do
- 1Grep every lockfile (
package-lock.json,yarn.lock,pnpm-lock.yaml,deno.lock) for the five malicious version pins:@asyncapi/generator@3.3.1,@asyncapi/generator-components@0.7.1,@asyncapi/generator-helpers@1.1.1,@asyncapi/specs@6.11.2,@asyncapi/specs@6.11.2-alpha.1 - 2Pin back to the clean predecessors:
@asyncapi/generator@3.3.0,@asyncapi/generator-components@0.7.0,@asyncapi/generator-helpers@1.1.0,@asyncapi/specs@6.11.1. All five malicious versions are now UNPUBLISHED from the public npm registry — but a private mirror (Verdaccio, Artifactory, Nexus, Cloudsmith) that cached them will keep serving them until manually purged - 3If any host installed or
required a malicious version: rotate ALL credentials that the affected process (or a developer using the same workstation) could reach — npm tokens, GitHub PATs and GitHub CLI config, SSH keys, AWS/GCP/Azure cloud credentials, browser-saved passwords, Slack/Discord/Telegram tokens, crypto wallets. Miasma implants persist through VS Code and Claude Code settings — inspect.vscode/tasks.jsonand.claude/settings.jsonon the affected workstations for injectedcommand/runTask/postCommandentries - 4Block outbound traffic to the known IOCs while incident-responding: primary HTTP C2 at
85.137.53.71(ports 8080, 8081, 8091), IPFS gateway fetch ofQmQobZSp1wRPrpSEQ56qnyq7ecZh5Bg5k1fnjt4SUwwHb9, and Ethereum contract callbacks to0x12c37A86a0Ed0beBe5d1d6a43E42f07860eAc710. Note that the implant's six-channel design means blocking these will not stop all C2, only make the operator's job harder - 5Audit every GitHub Actions workflow in your organization that uses
pull_request_target— the OWASP CI/CD Security Cheat Sheet and Chainguard's pwn request writeup both flagpull_request_targettriggers that check out the PR HEAD as a top-tier misconfiguration. Migrate to plainpull_requestwhere possible; whenpull_request_targetis required, do NOT check out the PR HEAD, do NOT expose repository secrets, and gate the workflow behindif: github.event.pull_request.head.repo.full_name == github.repository - 6If your organization publishes npm packages through GitHub Actions with npm OIDC trust, review the workflow scoping: the malicious AsyncAPI tarballs shipped with valid provenance because the workflow itself was hijacked. Consider requiring
environment:gating with manual approval on all publish jobs, and rotate the OIDC trust relationship if any actor-authored commit merged in the last 30 days - 7Assume the Miasma operator has multi-week persistence on any affected developer workstation. Full re-image (not just
npm uninstall) is the safe reset for a workstation that installed a malicious tarball
References
- SocketCompromised npm Packages in the AsyncAPI Namespace Deliver Multi-Stage Miasma Botnet Malwaresocket.dev
- Datadog Security LabsCompromised AsyncAPI npm packages: inside a CI supply-chain attacksecuritylabs.datadoghq.com
- StepSecurityCoordinated AsyncAPI Supply Chain Attack: Miasma RAT Delivered via Compromised CI/CD Pipelines in Two Repositoriesstepsecurity.io
- AikidoAsyncAPI npm packages compromised with Miasma variantaikido.dev
- AikidoAsyncAPI npm packages backdoored via GitHub Actionsaikido.dev
- WizM-Red-Team: AsyncAPI Supply Chain Compromise via GitHub Actionswiz.io
- OX SecurityAsyncAPI npm organization compromised, 2M weekly downloads affectedox.security
- ChainguardAsyncAPI supply chain compromise: npm packages backdoored via GitHub Actions "pwn request" (July 2026)chainguard.dev
- CloudsmithInside the AsyncAPI npm supply chain attackcloudsmith.com
- SafeDepAsyncAPI Packages Compromised with Miasma RATsafedep.io
- The Hacker NewsCompromised AsyncAPI npm Packages Deliver Multi-Stage Botnet Malwarethehackernews.com
- Security AffairsAsyncAPI npm Supply Chain Attack: Malware Injected Into Packages With 2 Million Weekly Downloadssecurityaffairs.com
- Developer TechFour AsyncAPI npm packages carry Miasma botnet loaderdeveloper-tech.com
- npm@asyncapi/generator on npm — package pagenpmjs.com
- npm@asyncapi/specs on npm — package pagenpmjs.com