AsyncAPI npm Packages Backdoored via GitHub Actions
Attackers pushed a poisoned commit to AsyncAPI's next branch and let its own GitHub Actions pipeline publish four npm packages carrying Miasma.
On July 14, 2026, attackers backdoored the AsyncAPI project's npm packages by pushing a poisoned commit to the source repository and letting the project's own GitHub Actions release pipeline publish it. Four packages in the @asyncapi namespace, including the widely used code generator, shipped a cross-platform malware loader that researchers are tracking as Miasma. The reason this AsyncAPI npm compromise matters is the delivery method. The malicious releases carry valid npm provenance and trusted-publishing attestations, because no npm token was stolen. The attacker abused the build system, so the registry's own integrity signals vouched for the malware. The affected packages pull roughly 2 million downloads a week, according to OX Security and Cyber Security News.
What happened
At 07:10 UTC on 2026-07-14, three packages from the AsyncAPI generator monorepo were published to npm within seconds of each other: @asyncapi/generator@3.3.1, @asyncapi/generator-helpers@1.1.1, and @asyncapi/generator-components@0.7.1. About an hour later a second batch added malicious releases of @asyncapi/specs, including @asyncapi/specs@6.11.2-alpha.1. Socket counts four compromised AsyncAPI packages in total. Each one carries an obfuscated dropper that fetches and runs the Miasma loader on macOS, Linux, and Windows.
One detail changes how you should respond. The malware runs when the library is imported, not when it is installed. That is different from the install-hook stealers that dominated the first half of 2026. npm 12 shipped on July 8 with dependency install scripts disabled by default, and that control does nothing here, because there is no preinstall or postinstall hook to block. The payload fires on require/import, so it runs inside any process that loads the package, including your build and codegen steps.
Timeline
- June 1, 2026: The Miasma loader first appears publicly, pushed into more than 30
@redhat-cloud-servicespackages through a compromised GitHub account, according to Palo Alto Unit 42. We covered the follow-on worm activity from that campaign separately. - July 14, 2026, 07:10 UTC:
generator-helpers@1.1.1,generator-components@0.7.1, andgenerator@3.3.1are published in the first batch, seconds apart. - July 14, 2026, around 08:06 UTC:
@asyncapi/specs@6.11.2-alpha.1is published in the second batch. Socket reports two maliciousspecsversions. - July 14 to 15, 2026: Wiz, Socket, StepSecurity, OX Security, Chainguard, Cloudsmith, and Upwind publish independent analyses within a day of each other.
Who is affected
AsyncAPI Generator turns AsyncAPI documents into code, documentation, and other artifacts. It is commonly run inside CI, so the blast radius is developer laptops and build runners rather than production web traffic. If a job installed one of the four bad versions and then executed it (a generator run, a test, a docs build), assume the loader ran with whatever access that process had. That typically includes npm tokens, GitHub Actions secrets, cloud credentials, and anything else reachable from the runner.
The @asyncapi/specs package is a common transitive dependency of the generator toolchain, which widens the set of projects that could have pulled a bad version without asking for it directly. Presence in a lockfile is the first thing to check, but with import-time malware it is not proof of execution on its own.
How the attack works
The entry point was a GitHub Actions "pwn request," according to Wiz and Chainguard. That is the common name for a pull_request_target workflow that checks out and runs code from an untrusted pull request while holding a writable token or repository secrets. Handled carelessly, that pattern hands an outside contributor the ability to run their code with the permissions of the target repository. In this case the result was push access to the project's next branch, as StepSecurity describes it.
From there the attacker did not need an npm token. They committed the implant to next, and the project's real release workflow built and published the packages using npm trusted publishing over OIDC. npm attributes all of the publishes to GitHub Actions (npm-oidc-no-reply@github.com), and the SLSA provenance attestations for the four packages point to the same GitHub-hosted runner and the same source commit. The provenance is genuine. It answers "who published this and where was it built," but it says nothing about whether the source was clean. Here the source commit itself contained the backdoor, so provenance vouched for a poisoned artifact.
Because the malware sits in the committed source, it shows up in the GitHub commit diff, not only in the npm tarballs. Socket reports that the poisoned commit modified three source files plus the package manifests. The first stage is a single obfuscated JavaScript statement dropped into otherwise normal code, using the familiar hex-style identifier pattern (names like _0x1dd48b). That statement pulls the larger payload from IPFS. Splitting the attack into a tiny on-registry trigger and a bigger off-registry payload keeps the npm footprint small and lets the operator swap the runtime payload without publishing a new version.
How to check if you are affected
Start with your lockfiles. Search every project and CI cache for the affected packages, then confirm the exact versions.
# Find any reference to the affected packages in lockfiles
grep -REn "@asyncapi/(generator|generator-helpers|generator-components|specs)" \
package-lock.json npm-shrinkwrap.json yarn.lock pnpm-lock.yaml 2>/dev/null
# Resolve what is actually installed in the tree
npm ls @asyncapi/generator @asyncapi/generator-helpers \
@asyncapi/generator-components @asyncapi/specs
Flag these exact versions as compromised:
@asyncapi/generator@3.3.1@asyncapi/generator-helpers@1.1.1@asyncapi/generator-components@0.7.1@asyncapi/specs@6.11.2-alpha.1
Because execution is import-time, decide whether the code actually ran. Review CI job logs from July 14, 2026 onward for any run that installed and then invoked the generator. On the network side, look for outbound connections from build runners to public IPFS gateways (for example ipfs.io, dweb.link, cloudflare-ipfs.com, w3s.link) during that window. Consult the Socket and StepSecurity write-ups for the current list of content identifiers and other indicators, which are still being updated.
Remediation
If you find a bad version, treat any host that imported or executed it as compromised and work through the following.
# 1. Remove the poisoned artifacts and the resolver cache
rm -rf node_modules
npm cache clean --force
# 2. Pin to a release published before 2026-07-14, or the patched
# version named in the AsyncAPI advisory, then reinstall clean
npm install @asyncapi/generator@<known-good-version>
As a stopgap in monorepos you do not want to bump immediately, block the specific bad versions with an override and reinstall from a fresh lockfile:
{
"overrides": {
"@asyncapi/generator": "3.3.0",
"@asyncapi/generator-helpers": "1.1.0",
"@asyncapi/generator-components": "0.7.0"
}
}
Set those pins to whatever the AsyncAPI advisory confirms as clean. Then rotate secrets. Because Miasma is a credential-stealing loader, revoke and reissue any npm tokens, GitHub personal access tokens, Actions secrets, cloud provider keys, and application credentials that were reachable from an affected runner.
Fix the underlying CI/CD weakness so this cannot recur. Do not run untrusted pull request code in a pull_request_target workflow that holds a writable token or secrets. Require review and restrict who can push to release branches such as next. Pin third-party actions to full commit SHAs rather than tags. Scope npm trusted publishing to protected branches and to environments that require a human reviewer, so a single poisoned commit cannot walk straight through to a signed release.
FAQ
Is AsyncAPI safe to use now?
The project's clean releases are fine. The four specific compromised versions are not. Avoid @asyncapi/generator@3.3.1, @asyncapi/generator-helpers@1.1.1, @asyncapi/generator-components@0.7.1, and @asyncapi/specs@6.11.2-alpha.1, and pin to a release published before July 14, 2026 or the patched version in the advisory. The compromise was in the build and release path, not a flaw in the library's design.
How do I know if I am affected by the AsyncAPI npm compromise?
Grep your lockfiles for the four packages and confirm the resolved versions with npm ls. Presence in a lockfile means you could have pulled the tarball. Because the malware runs on import rather than on install, also check whether any process actually loaded the package, using CI logs and outbound IPFS gateway connections around July 14, 2026. If it ran, treat the host as compromised and rotate credentials.
Does npm provenance or trusted publishing prevent attacks like this?
No. Provenance and trusted publishing prove that a package was built by a specific workflow from a specific commit. They do not prove that the commit was clean. In this incident the source commit already contained the backdoor, so the attestations were valid and still described malicious code. Provenance is useful for tracing an incident, not for deciding that an artifact is safe.
Did npm 12's install-script blocking stop this?
No. npm 12, released July 8, 2026, disables dependency install scripts by default, which blocks preinstall and postinstall payloads. This loader does not use an install hook. It runs when the package is imported, so the install-script control has no effect on it.
Sources
- Compromised npm Packages in the AsyncAPI Namespace Deliver Miasma · Socket
- Coordinated AsyncAPI Supply Chain Attack: Miasma RAT Delivered via Compromised CI/CD Pipelines · StepSecurity
- M-Red-Team: AsyncAPI Supply Chain Compromise via GitHub Actions · Wiz
- AsyncAPI supply chain compromise: npm packages backdoored via GitHub Actions pwn request · Chainguard
- AsyncAPI npm organization compromised, 2M weekly downloads affected · OX Security
- AsyncAPI npm Packages With 2M Weekly Downloads Compromised via GitHub Actions · Cyber Security News