Safeguard
DevSecOps

The AsyncAPI Hijack: When Trusted Publishing Becomes the Attack Path

On 14 July 2026 attackers used 37 pull requests against a pull_request_target workflow to steal the asyncapi-bot token, then let npm's OIDC trusted publisher automatically ship the malicious release. Four packages, 2.25 million weekly downloads, four hours live — and no code review was bypassed, because none was required.

Safeguard Research Team
Security Research
6 min read

The AsyncAPI compromise on 14 July 2026 is the most instructive supply chain incident of the month, and it has nothing to do with a vulnerable dependency.

The attackers did not find a CVE. They did not typosquat. They did not phish a maintainer. They used the project's own automation, exactly as it was configured to work.

What happened

Per GitGuardian's reconstruction, the sequence was:

  1. 37 pull requests were opened against AsyncAPI repositories, targeting a workflow triggered by pull_request_target.
  2. That workflow ran with elevated permissions in the context of the base repository — and the attackers used it to steal the asyncapi-bot personal access token.
  3. With the bot's identity, malicious commits were pushed directly. No review was bypassed, because a bot push did not require one.
  4. npm's OIDC trusted publisher then did precisely its job: it saw a legitimate, authenticated release event from the expected pipeline and automatically published the packages.

Affected: @asyncapi/generator, @asyncapi/generator-helpers, @asyncapi/generator-components, and @asyncapi/specs — five versions in total, across packages with roughly 2.25 million combined weekly downloads. The malicious versions were live from 07:10 to 11:18 UTC — four hours.

The payload was a multi-stage RAT staged from IPFS, with systemd persistence and command-and-control over HTTP, Nostr, an Ethereum smart contract, and a P2P mesh. Targets: browser passwords, SSH keys, npm and GitHub tokens, cloud credentials, and crypto wallets. It carried Miasma branding.

Why this one is different

Most supply chain defences are built on the premise that malicious code arrives from an untrusted source and can therefore be distinguished from legitimate code by origin. This attack defeats that premise completely.

  • The commit came from a legitimate identity (asyncapi-bot).
  • The release came from the legitimate pipeline.
  • The publish was cryptographically attested by OIDC trusted publishing — a control specifically designed to prove provenance.
  • Every signature, every attestation, every provenance claim was valid.

Provenance answered the question "did this come from the expected pipeline?" with a confident yes. It was the wrong question. The pipeline itself was the compromise.

This is not an argument against trusted publishing or SLSA provenance — both remain enormously valuable and you should absolutely adopt them. It is an argument against treating them as sufficient. Provenance establishes where an artifact came from. It says nothing about what the artifact does.

The pull_request_target footgun

If you take one operational action from this post, make it an audit of your pull_request_target workflows.

The trigger exists for a legitimate reason: pull_request workflows from forks run without secrets, which breaks labelling bots, coverage reporters, and preview deployments. pull_request_target solves that by running the workflow in the base repository's context — with its secrets and its permissions — while the PR's code sits right there.

The failure mode is when the workflow then checks out or executes any part of the untrusted PR. At that point an attacker who can open a pull request — which is to say, anyone — has code execution with your repository secrets in the environment. Thirty-seven attempts is not many when each one is free and the target does not fight back.

The safe patterns are well known and rarely applied consistently:

  • Never checkout the PR head in a pull_request_target workflow. If you must, do it into a directory nothing executes.
  • Keep the privileged workflow trivially small — read a label, post a comment — and do the real work in a separate unprivileged pull_request workflow.
  • Scope permissions: explicitly and minimally at the job level; the default is too broad.
  • Do not put long-lived PATs in CI at all. A asyncapi-bot PAT with push rights is a standing credential with no expiry and no scope ceiling.
  • Require review for bot pushes, or at minimum for pushes that touch release configuration.

The four-hour window is the real metric

Live for four hours. Detected and pulled reasonably fast, by ecosystem standards.

Now compare that to your own numbers. How long after a malicious version is published do you find out? For most organisations, the honest answer is: whenever a vendor emails them, or whenever it hits Hacker News — which for the July incidents was days. A package with 2.25 million weekly downloads distributes a great deal in four hours, and npm ci in a busy CI system does not wait for your threat intel feed.

The window between "malicious version published" and "you know you consumed it" is the single number that determines your exposure to this entire attack class. Everything else is downstream of it.

How Safeguard helps, at scale

Behavioural analysis over provenance-only trust. Because every provenance signal in this attack was valid, the only thing that could have caught it is what the code did. Safeguard's Supply Chain Core evaluates version-over-version behavioural deltas — a release that newly reaches out to IPFS, installs systemd persistence, and opens network paths its predecessor never touched is anomalous even when perfectly signed. Eleven scanners run against every version, so the finding does not depend on a CVE existing.

Sub-hour zero-day discovery, against a four-hour window. Safeguard's engine is built for time-to-detection rather than depth-of-report, with a track record of 50+ coordinated-disclosed zero-days and 1M+ scans completed. Against a four-hour exposure window, a scanning cadence measured in hours is the difference between "we blocked it" and "we are writing an incident report."

CI/CD posture, not just dependency scanning. Safeguard analyses your workflow definitions as part of the supply chain — flagging pull_request_target workflows that check out untrusted refs, over-broad permissions: blocks, long-lived PATs in secrets, and release paths that can be triggered by an unreviewed push. Across an org with 2,000 repositories, this is the only tractable way to find your own asyncapi-bot. Nobody audits 2,000 workflow files by hand.

Lion's JIT secret brokering, again. The thing actually stolen here was a standing token. Lion brokers credentials just-in-time and enforces egress allowlists, so a workflow that gets hijacked has no resident long-lived PAT to steal and no arbitrary destination to exfiltrate to. This is the structural fix; workflow hygiene is the tactical one.

Continuous SBOMs with transitive reach. @asyncapi/generator is a build-time tool; most teams that consumed it would not list AsyncAPI as a dependency if you asked them. Continuous CycloneDX and SPDX SBOMs across every repo and release make "did any pipeline anywhere pull one of these five versions in a four-hour window on 14 July" a query with an answer.

Griffin and Eagle for the response. Eagle prioritises which of your affected services were genuinely exposed rather than merely present in the dependency tree (~80% fewer false positives, remediation from 45 days to 3); Griffin authors and tests the pin-or-upgrade PRs across every affected repository at once, through your existing merge gates.

The AsyncAPI maintainers were not negligent — pull_request_target and OIDC trusted publishing are both recommended practice, and the combination is genuinely subtle. That is exactly why this pattern will keep working until people go looking for it in their own repositories.

Sources: GitGuardian: Four More Supply Chain Attacks Hit npm and PyPI · Unit 42: The npm Threat Landscape · Security Boulevard

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.