The 3 npm settings that stop most supply-chain attacks (lockfile, npm ci, cooldown)
The boring controls are the effective ones
Supply-chain attacks on npm get written up dramatically, but the defenses are unglamorous and that is the point. You do not need exotic tooling to blunt most of the risk — you need three settings that make your dependency installs predictable instead of opportunistic. None of them slow you down meaningfully, and each closes a common path in.
1. Commit your lockfile
Your package-lock.json records the exact version and integrity hash of every package in your tree, direct and transitive. Committing it means everyone — your laptop, your teammate, your CI — installs the same bytes, not whatever happens to be newest.
- Without a committed lockfile, a fresh install can silently pull a newer, just-published version of some deep dependency.
- With it, the version is pinned and the integrity hash is verified, so an unexpected change is caught.
This is the single highest-value habit, and it is just a file you keep in git.
2. Install with npm ci, not npm install
The difference is subtle and important. npm install may resolve and update versions, and can even rewrite your lockfile. npm ci does the opposite: it installs strictly from the lockfile, fails if package.json and the lockfile disagree, and never quietly upgrades anything.
- Use
npm ciin CI and production builds, always. - It makes your build reproducible and removes the moment where a surprise version sneaks in during deploy.
If your pipeline currently runs npm install, switching to npm ci is a one-line change with immediate benefit.
3. Add a publish cooldown
Many malicious package versions are caught and pulled within hours or a day of being published — but only if you did not install them in that window. A cooldown means you do not adopt a brand-new version immediately; you wait a short period so the community and registry have time to flag a bad release.
- Some tooling supports a minimum age or cooldown for new versions; where it does not, a short, deliberate delay before bumping dependencies achieves the same.
- Pair it with not auto-merging dependency bumps the instant they appear.
It is a small amount of patience that sidesteps the most acute window of risk.
What these three do not cover
These settings address how packages reach your build. They do not, by themselves, tell you whether a dependency you already ship is exposing something at runtime — a leaked key bundled from a package, a script loaded from a third-party origin, an outdated library reachable on your live site. That is the part an outside view catches.
Verify what actually ships
Good install hygiene and a live-site check are complementary. An automated scan looks at what your deployed site actually exposes — third-party scripts, reachable files, secrets in bundles — which is the runtime half of supply-chain safety. Scan your site to see what your dependencies put on the wire.