Contents
In brief
Headlines about hijacked npm packages keep returning, while “be careful what you install” does not scale to 1,200+ transitive dependencies. A Dev.to post maps the real threat model and five practical defense layers—without pretending npm can be perfectly safe.
What happened
package.json lists dozens of direct deps; node_modules holds hundreds or thousands. Each package can:
- run code at install time (
preinstall/postinstall); - be compromised after maintainer phishing;
- be typosquatted and pasted into a Dockerfile at 2am.
That runs before tests and linters—the moment you npm install.
Why it matters
npm cannot be made safe by default: the trust model is “run strangers’ code.” The gap between default installs and a hardened setup is still large.
| Measure | Effect |
|---|---|
ignore-scripts=true in .npmrc |
Cuts the main payload delivery path |
npm ci --ignore-scripts in CI |
No lockfile drift |
| Review lockfile diffs | Surfaces new transitive packages |
| Provenance (Sigstore) | Ties builds to repo and workflow |
| Exact pins + proxy (Verdaccio) + SBOM | Fewer surprises, faster incident triage |
In practice
- Today: set
ignore-scripts=true, thennpm rebuildonly trusted native deps (sharp,better-sqlite3). - Use
npm cionly in CI—notnpm install. - On dependency PRs, read package-lock.json, not just
package.json. - For critical services, exact-pin key dependencies (drop
^/~). - Keep secrets out of build environments that ever run install scripts.
Highest ROI single change: disable install scripts by default.
Takeaway
You cannot stop malicious publishes on the registry, but you can stop them from executing in your build environment. npm defaults are weak; your project does not have to inherit them.

