I recently opened an older Next.js project and ran npm install. The terminal immediately started reporting warnings. A quick pass with npm audit confirmed the state of the dependency tree: there were moderate, high, and even critical vulnerabilities waiting to be addressed.
found 23 vulnerabilities (15 moderate, 5 high, 3 critical)
Not great, but also not unusual for an older app. What matters is having a repeatable way to work through the list without turning the update into guesswork.
My three-step process
1 See what's wrong
Run a plain audit first and look at the severity and package names before changing anything.
npm audit
2 Auto-fix the easy ones
Let npm update packages that can be moved to safe versions without major breaking changes.
npm audit fix
3 Handle what remains
Use forced updates only after understanding the risk, because major version jumps can change runtime behavior.
npm audit fix --force
In this case the automatic pass fixed most of the moderate issues in build tooling, but a handful of vulnerabilities remained, including a critical issue in axios.
Real example: fixing axios
The critical package was axios at version 0.27.2. The reported issue involved potential SSRF exposure through URL parsing. The direct fix was simple.
npm install axios@latest
The tricky part is never just the installation. It is the behavioral change that can follow a major version bump. After updating to axios 1.6.0, I needed to revisit my error handling because response access was no longer safe to assume.
// My API utility before
try {
const response = await axios.get('/api/products');
return response.data;
} catch (error) {
console.log(error.response.status);
}
// After updating to axios 1.x
try {
const response = await axios.get('/api/products');
return response.data;
} catch (error) {
console.log(error.response?.status || 'Network error');
}
It is a small change, but exactly the sort of thing that can quietly break request flows if you treat dependency upgrades as purely mechanical.
What I do regularly
When it doesn't work
Sometimes npm audit fix --force still leaves vulnerabilities behind. In practice that usually means one of three things: the problem is buried deep in the dependency tree, the fix requires updating a major framework dependency such as next, or the package is no longer being maintained and needs to be replaced entirely.
| Situation | Likely next move |
|---|---|
| Vulnerability is deep in a transitive dependency | Inspect the dependency tree and identify the parent package that needs upgrading |
| Framework dependency is the blocker | Update Next.js itself and rerun the audit |
| Package is abandoned | Replace it rather than pinning yourself to an insecure version |
Bottom line
Running npm audit takes almost no time. Fixing what it finds can take longer, but it is one of the cheapest habits you can build into a project. A short dependency review every few weeks is far easier than responding to a preventable security incident later.