npm malware today looks less like isolated typosquatted packages and more like industrialized campaigns: self-replicating worms, multi-platform infostealers, and account takeovers of hugely popular libraries, most of which execute the moment you run npm install. The npm registry hosts millions of packages, and its openness is exactly what attackers exploit. Over 2025 the threat matured from opportunistic squatting into coordinated operations that compromise maintainer accounts and spread automatically. This is a rundown of what npm malware looks like right now and, more usefully, the concrete controls that keep it out of your builds.
The install-script problem at the root
Almost every npm malware technique depends on one feature: lifecycle scripts. When you install a package, npm can run preinstall, install, and postinstall scripts defined in its package.json, and those scripts run with your user's privileges on your machine or in your CI runner. That is the execution vector. A malicious package does not need you to import it or call its functions; it just needs you to install it, and the script fires automatically.
This is why modern npm attacks increasingly detonate inside CI/CD environments. A post-install script running inside GitHub Actions or GitLab CI can read environment variables, steal publish tokens, tamper with build artifacts, or push new malicious releases, all without a human ever looking at the code.
Shai-Hulud: the self-replicating worm
The clearest inflection point of 2025 was the Shai-Hulud worm in September. It was self-replicating malware that automated the compromise and redistribution of packages, and it infected over 500 npm packages in a coordinated attack. What made it a watershed was the mechanism: it did not just infect packages, it used compromised credentials to publish itself into further packages, spreading worm-style through the ecosystem.
The campaign originated from a phishing attack against a well-known maintainer, whose npm account was compromised through a fake domain impersonating npm's own support site. That single account compromise cascaded into 18 widely used packages, including chalk, debug, ansi-styles, and strip-ansi, which together account for around 2.6 billion weekly downloads. The lesson is uncomfortable: even the most trusted, most-downloaded packages are only as secure as their maintainers' credentials.
PhantomRaven and the infostealer wave
Between October and November 2025, researchers uncovered overlapping campaigns distributing credential stealers, including the Vidar infostealer. The PhantomRaven campaign consisted of 126 malicious packages that delivered multi-platform infostealers across Windows, Linux, and macOS, abusing preinstall and postinstall scripts to fetch secondary payloads from attacker-controlled servers.
A related wave used typosquatted package names to impersonate popular libraries and deployed a multi-stage credential harvester complete with fake prompts and IP-based fingerprinting to evade analysis. The pattern here is worth internalizing: the malicious package preserves the expected behavior of the library it impersonates, so nothing looks broken while your secrets are being exfiltrated in the background.
The techniques attackers actually use
Underneath the named campaigns, npm malware relies on a handful of repeatable techniques. Typosquatting registers names close to popular packages (a transposed letter, a missing hyphen) and waits for a fat-fingered install. Dependency confusion publishes a public package with the same name as one of your private internal packages, hoping your resolver grabs the public one. Account takeover, as with Shai-Hulud, hijacks a legitimate maintainer to push malware into a trusted package. And malicious install scripts, the common thread, execute the payload automatically on install. Recognizing these categories matters more than memorizing any single incident, because the incidents keep changing but the techniques persist.
How to defend your builds
The good news is that the defenses are concrete and mostly cheap. Start by disabling install scripts by default in CI, where you rarely need them:
npm ci --ignore-scripts
That single flag neutralizes the most common execution vector. If a specific dependency genuinely needs a build step, allowlist it rather than enabling scripts globally.
Pin and verify your dependencies. A committed package-lock.json plus npm ci (not npm install) means your CI installs exactly the versions you reviewed, so an attacker publishing a malicious new patch version does not silently reach your build. Consider a short cooldown before adopting brand-new releases, since many malicious versions are caught and pulled within days of publication; installing a package's version the moment it drops is the riskiest possible timing.
Lock down credentials. Scope npm publish tokens as narrowly as possible, prefer short-lived tokens, and never expose broad tokens in CI environments where a compromised dependency could read them. Enable two-factor authentication on your own maintainer accounts, because that is the exact control that would have blunted the phishing that started Shai-Hulud.
Where scanning fits
Human vigilance does not scale to hundreds of transitive dependencies updated weekly. Software composition analysis reads your full dependency tree and flags packages with known-malicious versions, suspicious install scripts, or recently disclosed advisories, ideally failing the build before a bad package is ever installed. An SCA tool such as Safeguard can surface a newly flagged malicious package transitively, several layers below your direct dependencies, which is exactly where these campaigns hide. Pair automated scanning with the install-script and lockfile hygiene above and you close most of the attack surface. Our pricing page lays out the scanning tiers if you want continuous monitoring rather than one-off checks.
FAQ
What is the most dangerous kind of npm malware today?
Self-replicating worms and account-takeover attacks against popular packages are the most dangerous because they abuse trusted, widely used libraries rather than obscure ones. The 2025 Shai-Hulud worm, which spread through compromised maintainer credentials into packages with billions of weekly downloads, is the defining example.
How does npm malware run without me calling it?
Through lifecycle scripts. When you install a package, npm can automatically run its preinstall and postinstall scripts with your privileges. Malware exploits this so it executes on install, before you ever import or use the package.
How do I stop npm install scripts from running?
Use npm ci --ignore-scripts in CI to disable them by default, and allowlist only the specific dependencies that genuinely need a build step. Combined with a committed lockfile and npm ci, this removes the most common execution vector.
Does two-factor authentication help against these attacks?
Yes, for the account-takeover class. The phishing that kicked off the Shai-Hulud campaign compromised a maintainer's npm login, and strong two-factor authentication on maintainer accounts directly blunts that path. It does not stop typosquatting or malicious scripts, which is why you layer it with dependency pinning and scanning.