decrypted · 15 july 2026 · vulnerabilities and patching · supply chain · digital sovereignty

A trusted GitHub workflow, and the three million downloads it poisoned

GitHub Actions gave an attacker three million weekly downloads' worth of npm packages this week, and it didn't take a zero-day to do it. On 14 July, a booby-trapped pull request against the AsyncAPI project's generator tooling stole a privileged access token, and within two hours five trojanised package versions were live on the public registry. Elsewhere, the UK quietly handed its financial regulators direct oversight of Microsoft, Google, Amazon and Oracle's cloud infrastructure, SonicWall disclosed a pair of zero-days already under attack, and Microsoft mapped a year of OAuth abuse against Salesforce customers. None of it needed a single unpatched CVE in the software the victims actually run.

A workflow that trusted its visitors

AsyncAPI is unglamorous plumbing: a code generator with more than three million downloads a week. On 14 July an attacker opened a pull request against the project's GitHub repository, one of dozens submitted that morning, most of them decoys. This one hid obfuscated JavaScript nearly a thousand bytes into a markdown file. The repository's continuous integration workflow ran on pull_request_target, a trigger that grants full repository secrets to a job while still checking out the pull request's own code rather than the trusted base branch. The script ran inside that privileged job, scanned the runner for secrets and exfiltrated a token to a public pastebin dead-drop within minutes. By 07:10 UTC, @asyncapi/generator 3.3.1 and three sibling packages were published with a three-stage payload: a small loader that, on import, pulled an encrypted second stage from IPFS, unpacking into a 92,000-line framework that persisted via systemd and harvested browser passwords, SSH keys, cloud credentials and crypto wallets.

The design flaw, not the exploit, is the story

pull_request_target combined with checking out untrusted PR code is a well-known anti-pattern, GitHub's own documentation warns against it. It is the equivalent of handing a visitor the office keys and alarm code, assuming you'd only ever deal with the receptionist, only to find the workflow lets the visitor bring in whatever they like and run it unsupervised. Chainguard's analysis found the vulnerable pattern had been flagged internally 58 days before the attack, with a fix left unmerged. That is the real failure: a known design risk left sitting in a backlog, not a missing patch. Worth noting too: because the attacker compromised the CI identity rather than an npm publishing token, the packages carried valid Sigstore and SLSA signatures throughout. Provenance tooling proves who signed a package. It says nothing about whether that signer was tricked. Any UK team running pull_request_target, or any privileged workflow that checks out contributor code, should treat this as a today problem.

Also this week

Sources

If your CI pipelines still trust pull_request_target with untrusted code, or you want a second opinion on your Secure by Design posture, get in touch.

More like this

Get the next post by email: subscribe to Decrypted. Double opt-in, unsubscribe any time, or take the RSS feed.