Unpacking the AsyncAPI npm supply chain compromise and import-time payload delivery
AsyncAPI npm packages compromised, delivering malware via import-time execution.
Summary
Threat actors compromised the @asyncapi npm organization, republishing five package versions with a malicious loader. This attack executed at module-load time, bypassing common npm security mitigations. The second stage involved downloading a Miasma runtime from IPFS for command and control.
Full text
Share Link copied to clipboard! TagsnpmSupply chain attackThreats intelligenceSupply chain attacksContent typesResearchProducts and servicesMicrosoft DefenderTopicsActionable threat insightsThreat intelligence On July 14, 2026, Microsoft Threat Intelligence identified a coordinated supply chain compromise of the @asyncapi npm organization, a widely used set of packages for the AsyncAPI specification and code generation. Five package versions across four package names were republished within roughly ninety minutes, each carrying the same maliciously injected loader: @asyncapi/specs (in both the 6.11.2-alpha.1 prerelease and 6.11.2 stable release), @asyncapi/generator@3.3.1, @asyncapi/generator-components@0.7.1, and @asyncapi/generator-helpers@1.1.1. Because @asyncapi/specs is a transitive dependency of numerous AsyncAPI tooling packages, this attack affected developer workstations, CI/CD pipelines, container builds, or production services that resolved and imported the affected versions during the exposure window. Unlike the more common postinstall-hook supply-chain pattern, this campaign executes at module-load (import/require) time. When any consuming build or application imports a poisoned package, the injected block runs immediately. Because the trigger is an import rather than an install script, the common npm install –ignore-scripts mitigation does not neutralize it. The second stage decrypts and evaluates a Miasma modular runtime with active command and control (C2), persistence, and decentralized fallback channels. Although disabled in this instance, credential-harvesting, propagation, and additional high-risk modules could be enabled through persistence. Microsoft Defender Antivirus detects and blocks malicious artifacts as Trojan:JS/MiasmStealer.SC and Trojan:Script/Supychain.A. Microsoft Defender for Endpoint provides behavioral coverage for the suspicious detached Node.js process spawn, IPFS retrieval, and persistence activity. Organizations should immediately remove all five affected versions, purge npm and Yarn caches, hunt for sync.js under the NodeJS masquerade directories, block outbound connections to 85.137.53[.]71 on ports 8080, 8081, and 8091, and rotate all credentials accessible from any environment that imported the compromised packages. Detailed hunting queries, indicators of compromise, and mitigation guidance are provided in the succeeding sections. Attack chain overview Figure 1. End-to-end attack chain from CI/CD pipeline compromise through import-time execution to IPFS second-stage fetch, with C2 infrastructure and affected packages. The compromise originated from a pwn request against asyncapi/generator. A misconfigured GitHub Actions workflow (pull_request_target) executed attacker-controlled pull-request (PR) code, exposed the asyncapi-bot personal access token (PAT), and enabled unauthorized pushes to auto-publish branches. The legitimate GitHub Actions OpenID Connect (OIDC) release workflows then published the poisoned packages under the automated identity npm-oidc-no-reply@github[.]com, producing artifacts with valid provenance signatures built from unauthorized source commits. The campaign progressed through six phases, shown in Figure 1: Pipeline compromise. The attacker exploited a vulnerable GitHub Actions workflow to steal a privileged bot token. Code injection. Heavily obfuscated loaders were inserted into one source file per package. Staged release. An alpha prerelease was followed by a stable release 24 minutes later, with a byte-identical payload, expanding blast radius. Delivery. Consumers pulled poisoned versions through normal npm and Yarn dependency resolution; –ignore-scripts was not effective. Import-time execution. require() or import triggered the malicious main(), which spawned a hidden detached child process. IPFS second-stage fetch. The child downloaded sync.js from IPFS and wrote it to an OS-specific “NodeJS” masquerade directory. The Miasma runtime provided encrypted bootstrap, persistence, C2 communication, data return paths, and resilient discovery via Nostr, Ethereum, BitTorrent DHT, libp2p, and IPFS. Six additional capability modules (credential harvest, encrypted exfiltration, supply-chain propagation, metamorphic generation, AI-tool poisoning, and sandbox evasion) were implemented but disabled in this build. Time (UTC)Observed event~07:10@asyncapi/generator@3.3.1, @asyncapi/generator-components@0.7.1, and @asyncapi/generator-helpers@1.1.1 republished with the injected loader.08:06:20@asyncapi/specs@6.11.2-alpha.1 published with the malicious importer prepended to index.js.08:30:09@asyncapi/specs@6.11.2 stable published with a byte-identical payload, widening downstream reach.08:49:22First observed downstream fetch of the stable 6.11.2 tarball into a Yarn cache during dependency installation. How the attack started: GitHub Actions pwn request The attack chain began with a malicious pull request targeting the asyncapi/generator repository’s docs-preview automation. Opened as PR #2155, it carried the attacker-controlled commit 47be388, timestamped 05:08:58 UTC on July 14. The associated Docs Preview (Netlify) workflow started at 05:11:05 UTC.. Although the PR and source fork were later removed, the workflow record remains available. The pull request PR #2155 targeted manual-netlify-preview.yml, which combined two unsafe choices: it used pull_request_target, placing the job in the base repository’s security context, and it checked out the pull request’s untrusted head commit. The run had a broadly privileged GITHUB_TOKEN, checkout credentials persisted in the local Git configuration until post-job cleanup (the default behavior of actions/checkout), and steps that referenced repository secrets. The submitted MDX contained code was designed to retrieve JavaScript from rentry[.]co/elzotebo999 and evaluate the response. The public log confirms that the malicious commit was processed by the privileged workflow, but it does not show whether the rentry[.]co web request succeeded or whether a credential was stolen. Later push records identify asyncapi-bot as the authenticated actor. Together, these records establish that the vulnerable workflow ran before the bot-authenticated pushes, but they do not establish how the credential was obtained. The underlying workflow weakness had been identified before the compromise. On April 29, a proof-of-concept examined whether untrusted pull-request content could be executed in the privileged docs-preview workflow. A May 17 proposal then sought to separate untrusted build activity from steps that received repository secrets and was still under review when the incident occurred. Trusted publishing became the delivery mechanism Once the attacker could push commits as asyncapi-bot, there was no need to compromise npm or construct a separate publishing channel. The attacker could ride the project’s normal release path and let its trusted pipeline do the distribution. Commit 3eab3ec carries a timestamp of 06:58:42 UTC, while a surviving push-triggered workflow started at 07:05:42 UTC. Its message, “fix: test release workflow on next”, matched the release workflow’s commit-message condition. The legitimate release-with-changesets.yml workflow then published three poisoned packages at approximately 07:10 UTC. A closely linked compromise subsequently affected asyncapi/spec-json-schemas. The malicious lineage first triggered workflows on alpha between 07:56 and 08:04 UTC. The same malicious commit was later pushed to master at approximately 08:14 UTC, followed by a child commit at 08:28 UTC. The legitimate if-nodejs-release.yml workflow published @asyncapi/specs@6.11.2-alpha.1 at 08:06 UTC and @asyncapi/specs@6.11.2 at 08:30 UTC. All five malicious versions were published through npm trusted publishing using GitHub OIDC and carried valid provenance attestations. The attestations accurately identified the legitimate repositories, commits, and workflows that created the
Indicators of Compromise
- domain — github.com
- ip — 85.137.53.71
- malware — Trojan:JS/MiasmStealer.SC
- malware — Trojan:Script/Supychain.A