A trusted namespace turned hostile
On July 14, the @asyncapi npm organization was compromised, and Microsoft Threat Intelligence, Aikido Security, Socket, and Wiz all published analyses within a day. AsyncAPI is a widely adopted specification for event-driven and message-based APIs, and its npm packages are dependencies deep inside build tooling and code generators across the industry. The attacker republished five malicious versions spanning four packages within roughly 90 minutes: @asyncapi/specs at 6.11.2-alpha.1 and 6.11.2, @asyncapi/generator at 3.3.1, @asyncapi/generator-components at 0.7.1, and @asyncapi/generator-helpers at 1.1.1.
The download math is what makes this serious. Combined, the affected packages see roughly 2.9 million weekly downloads, with @asyncapi/specs alone accounting for around 2.7 million. Every CI pipeline, container build, and developer machine that pulled a poisoned version inside the exposure window is a candidate for compromise. This is the recurring nightmare of the open-source dependency graph. A single upstream namespace with millions of weekly installs becomes a distribution channel that reaches thousands of downstream organizations at once, most of which have no direct relationship with the AsyncAPI project and no idea it sits in their build.
The way in was a GitHub Actions misconfiguration
The attacker did not steal an npm token or phish a maintainer. They exploited a misconfigured GitHub Actions workflow that used the pull_request_target trigger while checking out untrusted pull-request code. That combination is a well-known danger class, because pull_request_target runs in the base repository's security context with access to its secrets, and checking out attacker-controlled head commits lets external code execute with those privileges. On July 14, the attacker opened dozens of pull requests against the AsyncAPI generator repository, using the noise to camouflage the one that mattered, PR #2155, which triggered the vulnerable workflow.
The result was exposure of the asyncapi-bot personal access token and the ability to push commits into the branches that drive automated releases. From there, the attacker let the project's own legitimate release automation do the publishing. This is the pattern defenders need to sit with. The initial compromise came from a workflow that trusted external input it should never have executed, and it never required stealing a credential in the traditional sense. Continuous integration configuration has quietly become part of the production attack surface, and a single dangerous trigger in a public repository can be worth more to an attacker than a leaked password.
Valid provenance, malicious code
The most unsettling detail is that all five malicious versions were published through npm's GitHub OIDC trusted-publishing integration and carried valid SLSA provenance attestations. Those attestations accurately identified the legitimate repositories, the commits, and the workflows that built the packages. Every cryptographic check passed. The supply-chain assurance mechanism the industry has been promoting as the answer to package tampering confirmed the artifacts as authentic, because from the pipeline's perspective they were. The unauthorized commits had already been pushed into the repository before the trusted release workflow ran.
Aikido's Raphael Silva captured the attribution caution around the payload, noting that "the Miasma branding may reflect code reuse, imitation, or deliberate mislabeling. No definitive attribution is made here." The deeper lesson, as researchers summarized it, is that provenance does not protect against a compromised push credential. Attestation proves where and how a package was built. It says nothing about whether the source code was legitimate at build time. Organizations that adopted provenance verification as a control need to understand its precise boundary. It defeats artifact substitution after the fact, and it is blind to a poisoned commit that flows through the authorized pipeline.
A payload that runs on import
The malware was engineered to defeat the standard defenses. The attacker injected an obfuscated downloader into normal runtime modules, so the code executes at import time when a build or CI job loads the package, rather than through an install script. As Microsoft put it, "because the trigger is an import rather than an install script, the common npm install --ignore-scripts mitigation does not neutralize it." That single design choice sidesteps the advice most organizations have standardized on since the last wave of npm attacks. Disabling install scripts, long treated as a baseline hardening step, does nothing here.
On execution the loader fetches an encrypted Node.js bundle of roughly 8.2MB from IPFS, decrypts it through three layers of AES-256-GCM, and stands up what Microsoft identifies as the M-RED-TEAM Miasma runtime, a modular command-and-control framework with persistence and a real remote shell. Socket described the poisoned packages as shipping "a hidden JavaScript implant" that runs when imported during builds or CI jobs. Using IPFS for payload delivery and adding fallback channels over Nostr, Ethereum, BitTorrent DHT, and libp2p makes the infrastructure resistant to simple domain or IP takedowns, which extends the useful life of the campaign well past the point of initial disclosure.
CI credentials were the real target
The implant's collection logic reveals the intent. It targets more than 100 environment variables, and the list reads like an inventory of a modern build pipeline's secrets: GitHub and npm tokens, AWS keys, Azure credentials, Docker tokens, Kubernetes authentication, SSH keys, and API keys for AI platforms. This is not opportunistic data theft. It is a purpose-built harvester for the credentials that CI/CD systems hold, the ones that unlock cloud accounts, container registries, and further package-publishing rights. A single successful harvest can seed the next supply-chain compromise, turning one victim's pipeline into an attack platform against everyone downstream of them.
That target selection is a message about where value has moved. The environment variables sitting in a build runner are frequently more powerful than any single developer's laptop, because they carry the automation identities that deploy to production and publish to registries. The inclusion of AI platform keys reflects how quickly those credentials have become high-value, given the direct billing exposure and the access they grant to sensitive model integrations. We read this campaign as confirmation that CI/CD is now a primary objective in its own right, and that the secrets living there deserve the same guarding as production database credentials.
What to do now, and what to change
The immediate response is mechanical. Remove all five affected versions, purge npm and Yarn caches so a poisoned tarball is not silently reused, and hunt for a dropped sync.js file in directories masquerading as legitimate Node.js paths. Block outbound traffic to the reported command-and-control host at 85.137.53.71, and consider blocking public IPFS gateways at the perimeter given their role in payload delivery. Most important, rotate every credential that was reachable from any environment that installed a bad version, because token theft is the entire point of this malware and the harvested secrets are already gone if a build ran.
The structural fixes matter more than the cleanup. Audit GitHub Actions workflows for the pull_request_target pattern with untrusted checkout, which is the exact door the attacker walked through, and treat that configuration as a critical finding. Adopt npm's min-release-age controls, available in recent CLI versions, so pipelines do not immediately consume a package published minutes ago. And recalibrate expectations for provenance and attestation. They are useful controls with a specific scope, and this incident marks the point where the industry has to stop treating them as a complete answer to dependency risk and start pairing them with defenses that assume the pipeline itself can be turned against you.



