On August 4, 2026, an attacker took over the GitHub account of Jared Wray, the maintainer behind keyv, cacheable, and eight other widely used npm caching packages, and pushed malicious code straight to the main branch of each one. Within minutes, new versions were live on npm, cryptographically signed with valid GitHub Actions provenance, built and published through the exact same automated pipeline every legitimate release had gone through for years. The nine core packages Wray maintained directly, keyv, cacheable-request, cache-manager, cacheable, flat-cache, file-entry-cache, @cacheable/utils, @cacheable/memory, and @cacheable/node-cache, represent more than two billion combined monthly downloads. Worm-like propagation logic in the malicious payload then pushed compromised versions into hundreds of downstream packages that depend on them, expanding the blast radius well beyond anything a single maintainer's account should be able to reach. By the time researchers had it contained, 2,236 package versions across the family had been compromised.
What makes this attack worth a deep look, rather than a footnote in a weekly security digest, is not the scale on its own. It is that every control most teams already had in place, lockfiles, provenance verification, a trusted and long-established maintainer, failed to stop it, because the attack did not exploit a gap in those controls. It exploited the fact that a real human with real, unrevoked publishing rights had their account taken over, and everything downstream of that account was, by design, supposed to be trusted.
Once the attacker had control of the maintainer's GitHub account, the attack itself was straightforward. Malicious commits went directly to the main branch of each affected repository, and a new release was cut immediately afterward, before anyone reviewing the account activity would have had a realistic window to notice and revoke access. Every affected package version received two new files, setup.mjs and Math_Symbol.js, along with a "preinstall" entry added to package.json pointing at setup.mjs. That single line meant the malicious script executed automatically, before the rest of the install even completed, on every machine that ran npm install against an affected version, with no developer action beyond a routine dependency install required.
The payload itself was a credential-stealing dropper. On execution, setup.mjs downloaded the Bun runtime and used it to run a heavily obfuscated, roughly 728 KB stealer that scanned the host machine for .npmrc publish tokens, GitHub CLI tokens, AWS credentials, HashiCorp Vault tokens, Kubernetes configuration files, and cryptocurrency wallet data, then exfiltrated whatever it found. The design targets exactly the credentials that live on developer laptops and, more consequentially, on CI runners, where a single compromised build job can hold publish rights, cloud infrastructure access, and secrets management tokens all at once.
Teams that adopted npm's provenance attestations, the cryptographic proof, generated via GitHub Actions OIDC, that a published package was built from a specific commit in a specific repository through a specific workflow run, had good reason to think they had closed the biggest supply chain hole. Provenance genuinely does solve a real problem: it makes it much harder for an attacker with a stolen npm publish token to quietly push a malicious release from their own laptop, because the published package would carry no matching attestation.
That is not the attack that happened here. The attacker did not need a stolen npm token, because they controlled the GitHub account with commit access to the source repository itself. Every malicious release went through the real CI pipeline, built from the real, now-poisoned, source, and signed by the real workflow. Every attestation was completely valid, because provenance proves the package matches what the pipeline built, not that what the pipeline built is safe. Any team using "has valid provenance" as a sole supply chain gate would have watched all 2,236 malicious versions sail straight through that check with a green light attached.
Most engineering teams we talk to have some subset of the relevant controls in place already. Very few have all of them, and this attack found the gaps.
None of the fixes here require exotic tooling, but they do require someone to actually go do the work before the next worm, not after.
The organizations that came through this cleanly were not the ones with the most security tooling installed, they were the ones that had already made --ignore-scripts the default and treated CI credentials as narrowly scoped, short-lived, and disposable well before August 4. Auditing a dependency pipeline for exactly this kind of blast radius, lifecycle scripts, credential scope, lockfile discipline, and egress visibility, is core to the production-hardening work we do as part of our software and web development engagements. If your team cannot currently answer what an average dependency's install script is allowed to touch in your CI environment, that is the place to start.
Before we start, please share a few details so we can follow up with you.
End this conversation? Your chat will be emailed to us.