Skip to content

Security1 publisher3 min readPublished

Shai-Hulud's fourth wave shipped with valid provenance, and that is the finding

The poisoned keyv releases were signed by GitHub Actions and the attestation was accurate. It certified a build whose source had already been taken over.

The Watch · Security desk

Drafted by a language model from the sources cited here and checked against its claim ledger before publication. How we use AISend a correction

What happened

  • On the morning of August 4, someone took over the GitHub account behind keyv, a caching library with roughly 127 million weekly downloads.
  • The attacker pushed malicious code from a new Shai-Hulud npm campaign straight to the main branch and cut a release.
  • The poisoned versions were published to npm carrying valid provenance, signed by GitHub Actions.
  • Within hours the worm had spread to more than 1,280 packages representing more than 2 billion monthly installs.
  • Researchers at Aikido Security and Endor Labs were watching 50 to 100 new packages fall every few minutes.

Compiled by The WatchSomething wrong?How this is made

Why it matters

On August 4, according to an SC Media Perspectives commentary, someone took over the GitHub account behind keyv, a caching library with roughly 127 million weekly downloads, pushed code from a new Shai-Hulud campaign to the main branch, cut a release, and published it to npm carrying valid provenance signed by GitHub Actions [1] [2] [3]. That last clause is the finding: the attestation was correct, because the attacker committed through the project's real repository and triggered its real workflow, so the pipeline honestly certified a poisoned build [7].

Anyone who read attestation as a verdict got exactly what the control promises and nothing they actually needed. Build provenance proves where and how a package was compiled and published; it says nothing about whether the source that went in was trustworthy [6]. After the first three waves, the commentary notes, industry guidance had converged on two controls: scan dependencies, demand attestation [8]. Both are worth doing, and neither answers the question at install time. Signing infrastructure inherits the trustworthiness of whoever can trigger it, so a compromised maintainer account produces a faithfully signed malicious release with no cryptography broken anywhere [9].

The scale numbers followed from automation, not from attacker effort. Within hours the worm reached more than 1,280 packages representing more than 2 billion monthly installs, with researchers at Aikido Security and Endor Labs watching 50 to 100 new packages fall every few minutes [4] [5]. Note that keyv alone, at 127 million weekly downloads, is on the order of a quarter of that headline install figure, so the 2 billion is a measure of blast radius, not of how many separate compromises occurred [18]. The spread mechanism was continuous integration: build runners install transitive dependencies and hold publishing tokens for service accounts, and the payload harvested those tokens and republished poisoned versions of each victim's own packages with no human attacker in the loop [15].

The execution path is built to defeat scanning as well. Every infected package carried a preinstall hook and a file named setup.mjs, an obfuscated dropper that pulls down the Bun runtime and uses it to run a 728 KB payload called Math_Symbol.js [10]. The stealer runs in memory and finishes before npm install does, leaving almost nothing on disk to find [11]. It goes after npm and GitHub tokens, AWS credentials, Kubernetes secrets, HashiCorp Vault tokens, and Stripe and Slack keys [12], and sweeps roughly 200 filesystem patterns for SSH keys, Terraform state, Docker registry credentials, KeePass databases and VPN configuration [13]. The results were encrypted and pushed to a public GitHub repository described as "Shai-Hulud: Here We Go Again." [14]

The remediation list in the commentary is unglamorous and cheap: turn install scripts off by default in CI, pin versions and use overrides, rotate on the assumption of exposure rather than evidence of it, stop treating attestation as a decision, and place a control at the moment code executes [16]. The pinning advice matters most for teams that audited direct dependencies and found nothing, since the affected caching libraries are usually transitive [17].

Watch whether the post-wave guidance changes shape. If the answer remains scan and attest, the fifth wave has the same entry point available: one maintainer session, one real workflow, and a signature that verifies [9] [7].

Loading claim ledger
Loading source directory links
Loading share composer
Loading topic controls
Loading related stories