Maintain npm dependencies by committing package-lock.json, installing in CI with npm ci, running npm audit regularly, updating in small reviewed batches, and verifying signatures and provenance where available. A routine beats heroics: small, frequent updates are easier to review than a yearly leap.
Why does the lock file matter?
package.json describes ranges of acceptable versions. The lock file records exactly what was installed. The npm documentation says npm ci is meant for automated environments such as test platforms and continuous integration, and that it installs a project with a clean slate: it removes any existing node_modules, never writes to package.json or any lock file, and exits with an error if the lock file and package.json do not agree.
So in CI, npm ci gives repeatable installs. On a developer machine, npm install updates the lock file, and that change should be reviewed in a pull request like any code.
What does npm audit do?
npm audit submits a description of your dependency tree to the registry and reports known vulnerabilities. The docs say it exits with code 0 if no vulnerabilities were found, and that the exit code otherwise depends on the audit level setting, which makes it usable as a build gate.
npm audit fix installs compatible updates to vulnerable dependencies. A variant that only updates the lock file leaves node_modules alone. Treat automatic fixes like any update: review the diff and run tests.
The docs also note that omitting dev dependencies from an audit changes what is submitted, so decide whether you care about build tooling risk as well as production risk. Most teams should.
How do you verify what you installed?
npm audit signatures verifies registry signatures and the provenance attestations of downloaded packages. npm's documentation notes that provenance is a new feature and the attestation format may change over time, so keep your npm client current.
Provenance tells you where a package was built. It does not tell you the code is safe, so it complements review rather than replacing it.
What is a sensible update routine?
A constructed example: a team of six sets a weekly slot. On Tuesday one person runs npm outdated, groups updates by risk, applies patch and minor updates in one pull request, and puts any major version in its own pull request. CI runs npm ci, the test suite and npm audit. Security fixes with known exploitation skip the queue and ship the same day.
Small batches mean that when something breaks, the cause is one of five changes, not fifty.
How do you reduce the dependency surface?
Remove packages you no longer use. Prefer a standard library function to a package that wraps it. Ask of each new dependency who maintains it, how often it releases and how many packages it brings along. Remember that installs can run lifecycle scripts, so a new transitive package can execute code on your build machine.
Where does Safeguard fit?
Safeguard scans project dependencies and generates an SBOM, and reachability analysis helps separate vulnerable packages that your code actually calls from those that merely sit in the tree. The free scan at gold.safeguard.sh/scan covers up to 100 dependencies and runs in the browser.
How to check or apply this
- Commit package-lock.json and review changes to it in pull requests.
- Use npm ci in CI and in container builds.
- Run npm audit in the pipeline and set the audit level you will fail on.
- Run npm audit signatures to verify signatures and provenance.
- Update weekly in small batches, with majors in separate pull requests.
- Expedite fixes for actively exploited vulnerabilities.
- Remove unused packages and review each new dependency's maintainers.
- Keep Node.js and npm themselves up to date.
Quick check
What is the difference between npm install and npm ci?
npm install can change the lock file. npm ci installs exactly what the lock file lists, starts clean and fails if package.json and the lock file disagree.
Does npm audit find every problem?
No. It reports vulnerabilities known to the registry's advisory data. It does not detect malicious packages that have no advisory yet.
Sources
Last reviewed: 18 October 2026.