Definition
A maintainer account takeover is when an attacker gains control of a package maintainer's registry account or publish token, through phishing, password reuse or a leaked token, and uses it to publish a malicious version of a trusted package.
How accounts get taken over
- Phishing: a convincing "please update your 2FA" email on a look-alike domain captures the password and one-time code.
- Leaked tokens: long-lived publish tokens in
.npmrcfiles, CI logs or public repositories. - Worms: malware that steals tokens from every machine it runs on and uses them to publish more infected packages.
- Expired domains: re-registering a maintainer's lapsed email domain to reset their password.
Real incidents
- eslint-scope (2018): a reused password let attackers publish a version that stole npm tokens.
- ua-parser-js (2021): a hijacked account published versions carrying a cryptominer and a password stealer.
- chalk, debug and others (2025): a maintainer was phished through a fake npm support domain, and malicious versions that rewrote crypto wallet addresses in browsers were live for a few hours.
- Shai-Hulud (2025): a self-replicating worm harvested npm and GitHub tokens and republished infected versions of hundreds of packages.
Defenses
For maintainers: use phishing-resistant 2FA (security keys or passkeys), publish from CI with trusted publishing (OIDC) instead of long-lived tokens, and enable provenance so users can verify where a release was built.
For users: pin versions with a lockfile, avoid adopting releases in their first hours or days, watch for install scripts that appear in a patch release, and scan new versions' source before upgrading.
Frequently asked questions
How can I tell if a package version was hijacked?
Warning signs include a new install script in a patch release, minified or obfuscated code in a package that never had it, a release with no matching tag or commit in the repository, and missing provenance on a package that normally has it.
Does npm provenance stop account takeover?
It helps users verify that a release was built from a specific repository and workflow, so a version published by hand from a stolen token stands out, but only if users check for it.