npm・Using it safely

npm's scary story—protecting yourself, learned from the Shai-Hulud incident

The 'supply chain attack' where malicious code sneaks into npm parts. This explains the tactics of the real Shai-Hulud incident that happened in 2025, and five defensive habits even a beginner can start today.

npm is a system for “putting some stranger’s parts on your own PC and running them.” That’s exactly why you’ll want to know about the supply chain attack—an attack that mixes poison into the supply route of parts—and its headline example, the Shai-Hulud incident. It looks like a hard topic, but the core of the defense is “install habits,” which means beginners are in a good position to protect themselves starting today.

npmWhat is npm? What does npm install actually do?If npm and node_modules haven’t quite clicked yet, read this first

A supply chain attack mixes poison into the materials

Hacking your site directly is hard work. So attackers changed their thinking—if you plant poison in the parts (packages) everyone uses, the poison reaches everyone who installs them. This is the supply chain attack.

npm packages have a mechanism that can run an attached program the moment you install them. In other words, an infected part starts running on your PC the very moment you type npm install. It doesn’t even wait for you to build or run anything.

The Shai-Hulud incident—a self-replicating “worm”

In 2025, this attack became reality on an unprecedented scale. The name comes from the giant sandworms in the novel Dune.

  • September 2025 (first wave)—installing an infected package searches for and steals the npm and GitHub credentials (master keys) on the PC. Then, using those stolen keys, it plants poison in other packages that same developer publishes and republishes them—a “worm (self-replicating type)” that spread the infection without any human involvement
  • November 2025 (second wave, “The Second Coming”)—an even larger-scale return. About 800 packages and over 1,000 versions, including well-known names like Zapier, PostHog, and Postman, were contaminated, and the stolen information was published to tens of thousands of GitHub repositories

The victims weren’t “people who visited a shady site.” They were developers who just ran npm install as usual. That’s the scariest part of this incident.

Defense 1: Pin versions to “exact”

If a version in package.json is a range specifier like ^1.2.3, then whenever you install without a package-lock.json in place (a fresh install, an install after deleting the lock, or the lock-updating install covered in Defense 2), the newest version within that range at that moment gets installed. Install right after a poisoned new version is published, and you’ll pull it in automatically—the very route Shai-Hulud spread through.

If you keep it to an exact specifier with no symbols (version pinning) like 1.2.3, it won’t advance to a newer version on its own. Updating becomes a deliberate act of “choosing to bump it yourself.”

npm config set save-exact true

With this setting, from then on npm install <name> automatically records the exact version, with no ^ attached.

Defense 2: Cherish package-lock.json

package-lock.json is “an exact record of all the parts that were actually installed.” Put it in Git, and the next install brings in the same parts exactly as recorded. Even if a range specifier ^ remains, the lock file is the insurance that keeps things from drifting.

  • Always commit it to Git (don’t put it in .gitignore)
  • In CI and reinstalls, using npm ci installs in a form that matches the lock file’s record exactly
npmHow to read package.jsonThe relationship between package.json and package-lock.json is covered in detail here

Defense 3: Don’t jump on a brand-new version

A poisoned version is usually found and deleted within hours to a few days of publishing. Put another way, right after publishing is the danger zone. Instead of bumping the moment “a new version is out!”, just waiting a few days to two weeks before bumping greatly lowers the risk. In fact, after Shai-Hulud, even major companies adopted the practice of “don’t install a new version for 14 days after it’s published.”

Defense 4: Don’t casually npm install unfamiliar projects

A program runs the moment you install—which means running npm install on a project of unknown origin you picked up on GitHub is like pressing the run button on a stranger’s program. If you only want to try it, there’s an option that stops the attached program from running.

npm install --ignore-scripts

Defense 5: Take a breath before installing—checking a package’s “identity”

Before adding a new package, spend just 30 seconds looking at its page on the npm official site.

  • Weekly download count—be cautious with ones that are extremely low
  • Spelling of the namefakes that impersonate common typos of popular package names (typosquatting) really do exist
  • Last updated date and description—is it abandoned, does the description make sense
The npm page for the astro package. In the right column, a weekly download count of 3.24 million, the version, and the last publish date are lined up
The right column of a package page is the identity-check corner. You can confirm Weekly Downloads and Last publish right here.

Defense 6: Check what you already have with npm audit

There’s also a command that checks all at once whether any known vulnerabilities exist among the parts already installed.

npm audit

It shows a list with severity levels, and you can also try automatic fixes with npm audit fix (it can jump all the way up to a new major version, so don’t forget to check that things still work after a fix).

Summary of this lesson

  1. A supply chain attack mixes poison into the parts. On npm, the poison runs the moment you npm install
  2. The Shai-Hulud incident (2025) was self-replicating and contaminated hundreds of packages—the victims were “people who installed normally”
  3. Defense is about habits: pin versions, put the lock file in Git, don’t jump on new versions, avoid installs of unknown origin, and check the identity before installing

We’ve told a scary story, but the goal isn’t to scare you—it’s to help you learn how to buckle your seatbelt. Once it becomes a habit, you can enjoy the benefits of the parts with peace of mind.

FAQ

What is a supply chain attack?
Instead of targeting the thing you want to make directly, it poisons the supply route of the materials and parts. On npm, it happens by slipping malicious code into a new version of a popular package, then stealing information from the PC of anyone who installs it.
What was the Shai-Hulud incident?
It was one of the largest attacks in npm history, occurring in September and November 2025. Installing an infected package stole credentials, and using those stolen permissions it spread the infection to yet more packages—a 'self-replicating worm' that contaminated hundreds of packages in total.
Are there measures even a beginner can take?
Yes. Pin versions without the ^, put package-lock.json in Git, don't jump on brand-new versions the moment they appear, and don't casually npm install unfamiliar projects—just habits around installing can greatly reduce the risk.
What is npm audit?
It's a command that checks all at once whether the parts already installed on your machine have any known vulnerabilities. Running it regularly lets you confirm for yourself that no dangerous parts have slipped in.