Shai-Hulud 2.0 and the npm Maintainer Account Problem
Why package maintainers are the target
A dependency attack does not need a vulnerability. It needs a publishing credential. When an attacker holds a maintainer account, every downstream consumer installs attacker code through the normal, expected update path. JFrog's analysis of a new Shai-Hulud variant describes that pattern: a campaign that spread across more than 400 npm packages and more than 1,700 package versions.
How the campaign worked
The analysed payload came from a compromised keyv@6.0.0 release, packaged as a roughly 710 KB JavaScript file. keyv and cacheable are caching libraries, and keyv appears as a transitive dependency of many popular tools, so the affected surface extended well past projects that name it directly.
The payload had four objectives, according to JFrog's public analysis.
- Harvest secrets from local files, CI/CD environments, cloud metadata endpoints, Kubernetes, and HashiCorp Vault.
- Exfiltrate encrypted data through dynamic HTTPS endpoints or attacker-controlled public GitHub repositories.
- Republish patched versions of any package the stolen npm credentials could write to.
- Abuse GitHub credentials and GitHub Actions workflows to infect repositories and collect further credentials.
The sample SHA-256 recorded in the analysis is
9fc2570b7cef51c1b8df116d144d11ff4096357be7d2c4c6367cfc2509cf1bcc. One operational detail limits impact for part of the ecosystem. In npm 12 and later thepreinstalllifecycle hook does not run by default, so the payload does not execute during installation on those versions. That is a default change rather than a fix, and it does not apply to older runtimes or to projects that re-enable the hook.
Why this keeps happening
The JFrog findings fit a documented pattern. Public supply chain timelines from Sonatype describe repeated waves through 2025 and 2026 in which maintainer credentials were stolen and used to publish malicious updates: debug and chalk in late 2025, a self-propagating npm worm, then compromises of security tooling and AI-adjacent libraries in March 2026, followed by bulk malicious pull requests and the compromise of an account behind a widely used HTTP client.
The economics are straightforward. Attacking one maintainer account yields distribution to every project that depends on the package, without needing to find a flaw in the package itself. Registry-level publication is trusted by design, which is what makes the technique efficient.
Defensive implications
Detecting this class of attack requires watching publication events, not only code.
- Enable provenance and signed attestations where supported, and treat unattested version bumps of widely used dependencies as review events.
- Pin dependencies and commit lockfiles, so an unexpected version change becomes visible in review rather than in production.
- Scope registry tokens to individual packages and short lifetimes, and rotate them on any suspected exposure.
- Treat CI/CD secrets as production credentials. A workflow that can read cloud metadata or Vault should be reviewed on the assumption that it runs attacker code.
- Monitor for unexpected publish activity from legitimate accounts, and for new
postinstallorpreinstallscripts in dependency updates. Two limits are worth stating. Scanning for known malicious versions only covers versions already catalogued, and a compromised maintainer can publish again.preinstallbehaviour also differs across npm versions, so organisations on older toolchains should verify their own runtime rather than assume the default protects them.
References
- JFrog security research, Shai-Hulud variant affecting 400+ npm packages, 8 September 2026: https://www.jfrogchina.com/blog/shai-hulud/
- Sonatype, history of software supply chain attacks: https://www.sonatype.com/resources/vulnerability-timeline
- MITRE ATT&CK T1213.003 Code Repositories: https://attack.mitre.org/techniques/T1213/003
Top comments (0)