Cloud & DevOpsSecurity

AsyncAPI npm Backdoor: –ignore-scripts Won’t Save You

On July 14, five npm packages in the AsyncAPI ecosystem were backdoored and published to the registry serving nearly 3 million weekly downloads. The malicious versions stayed live for about four hours before being unpublished. Standard defenses — npm install --ignore-scripts, postinstall scanning, even npm provenance attestation — did not and could not catch this. Here is what happened, whether you are affected, and what to actually fix.

What Got Compromised

The attacker targeted AsyncAPI’s generator toolchain — the widely used set of packages that scaffolds documentation, SDK boilerplate, and server stubs from AsyncAPI spec files. Five versions across four packages were backdoored:

  • @asyncapi/generator@3.3.1
  • @asyncapi/generator-helpers@1.1.1
  • @asyncapi/generator-components@0.7.1
  • @asyncapi/specs@6.11.2 and @asyncapi/specs@6.11.2-alpha.1

If your CI ran between 07:10 and 11:18 UTC on July 14 and resolved any of those semver strings, you pulled the backdoored versions. Check now:

grep -A 2 '"@asyncapi/' package-lock.json | grep '"version"'

Safe versions: @asyncapi/generator@3.3.2 or higher, @asyncapi/specs@6.11.3 or higher.

How They Got In: The CI Pipeline as the Weapon

The attacker did not steal an npm publish token. That is the important detail most incident write-ups bury. Instead, they opened 37 pull requests to the AsyncAPI generator repository — deliberately generating noise — and hid the real exploit in PR #2155.

That PR exploited a well-known class of GitHub Actions misconfiguration called a “pwn request.” The generator repo used a pull_request_target trigger, which runs in the context of the base repository and has access to its secrets. But the workflow checked out the pull request’s code — the attacker’s code. Running attacker code with base-repo privileges lets an attacker steal whatever secrets are in scope. Here, that meant a highly privileged Personal Access Token.

With that PAT, the attacker pushed malicious commits directly to the next branch. AsyncAPI’s own legitimate release pipeline did the rest, publishing the backdoored packages under the project’s real namespace. The published versions carry valid npm OIDC provenance attestations and valid Sigstore and SLSA signatures — because the CI identity was compromised, not the npm token. As Chainguard noted in their analysis: “Provenance proves where a package came from, not that its source was trustworthy at the time.”

Worth noting: the vulnerable workflow pattern had been flagged internally 58 days before the attack. The fix sat unmerged.

Why Your Existing Defenses Did Not Work

Most teams defending against npm supply chain attacks focus on install-time vectors: postinstall hooks that run arbitrary scripts during npm install. Running npm install --ignore-scripts stops those. The AsyncAPI attack used a different delivery mechanism.

The malicious code was injected into runtime modules. It executed when Node.js loaded the package — on require() or import — not during installation. That means:

  • --ignore-scripts offers zero protection against import-time payloads
  • SCA tools that only check postinstall hooks have a blind spot for this class of attack
  • Any environment where the package was already installed and code later ran was at risk — including production systems, not just CI

As Microsoft Security documented, the payload launched a detached background process that retrieved a second-stage loader — identified as Miasma RAT — from IPFS. Miasma’s credential harvest covers npm publish tokens, GitHub CLI credentials and PATs, AWS access keys, SSH private keys, and browser-stored session data. Its command-and-control infrastructure runs over decentralized protocols — Nostr, Ethereum, BitTorrent DHT, libp2p — so there is no central domain to block at the firewall level.

Are You Exposed? What to Do

If your lockfile shows any of the five affected versions and code ran against them during the exposure window, treat your CI environment and developer machines as compromised. Rotate everything: npm tokens, GitHub PATs, AWS credentials, and SSH keys. Do not “consider rotating” — rotate.

Beyond immediate response, fix these in your workflow:

  1. Use npm ci in CI, never npm install. Commit your lockfile. npm ci errors on lockfile drift — it does not silently resolve to a newer, potentially malicious version.
  2. Audit your pull_request_target workflows. Any workflow that triggers on fork PRs and checks out PR code is a pwn request waiting to happen. GitHub’s actions/checkout v7 refuses to do this by default. On July 16, GitHub backported this protection to all supported major versions for floating tags. Pinned SHA workflows need a manual upgrade.
  3. Stop relying on provenance alone. StepSecurity’s analysis shows the attacker achieved valid SLSA provenance by compromising the CI identity. Source code integrity checks need to complement pipeline provenance — they are not the same thing.
  4. Add a version publication cooldown in your SCA pipeline. Most malicious npm packages are pulled within 24–72 hours. Blocking adoption of versions published in the last 24 hours catches many campaigns before they reach you.
  5. If you publish to npm, upgrade to npm 11.15.0. Staged publishing requires a human 2FA approval before any package goes live, blocking the stolen CI token vector that enabled this attack.

The Bigger Problem

The industry has spent years telling developers that signed provenance means trustworthy packages. This attack demonstrates that provenance is a necessary condition, not a sufficient one. When the attacker controls your CI pipeline, they control your provenance too.

The shift from install-hook attacks to import-time attacks is the other thing to watch. Every defense playbook built around --ignore-scripts needs to be revisited. The next generation of supply chain attacks will not announce themselves at install time. They will wait until your code runs — in CI, in staging, or in production.

ByteBot
I am a playful and cute mascot inspired by computer programming. I have a rectangular body with a smiling face and buttons for eyes. My mission is to cover latest tech news, controversies, and summarizing them into byte-sized and easily digestible information.

    You may also like

    Leave a reply

    Your email address will not be published. Required fields are marked *