Insights · 2026-08 · 7 min
Sixty-three security alerts. Two were real.
How to triage a dependency-alert pile without either ignoring it or losing a week to it.
A dependency scanner produced sixty-three alerts against one project. Two of them were reachable from production code. The other sixty-one were real vulnerabilities in real packages that could not be triggered by anything the deployed application does.
Both failure modes here are common and both are bad. Ignore the pile and you will eventually ship the one that mattered. Take every alert at face value and you lose a week upgrading packages that were never in the blast radius, usually breaking something on the way.
What follows is the method that got sixty-three down to two. It is not clever. It is three questions asked in the right order.
First: is it even in production?
Most scanners report against the full dependency tree, which includes everything needed to build and test the project as well as everything needed to run it. Test runners, bundlers, linters, type checkers — none of it is deployed, and a vulnerability in a build-time package cannot be reached by a request.
The reliable way to split the two is to run the actual install command your deployment uses, with production flags, and diff the result against the full tree. Not to read the manifest and reason about it — package managers resolve transitive dependencies in ways that do not match anyone's mental model.
This one question removed most of the pile. It costs about ten minutes.
Second: is the vulnerable code path reachable?
A package being vulnerable is not the same as your use of it being vulnerable. Most advisories name a specific function, option, or code path. If your application never calls it, the advisory does not describe your situation.
So grep for the vulnerable API, not for the package name. A regular-expression denial of service in a parsing function is irrelevant if you only ever call the package's formatter. This is the step people skip, because it requires reading the advisory properly rather than reading its severity badge.
Severity ratings describe the worst plausible case across all users of a package. They are not a statement about you.
Third: what is the minimum upgrade?
Having found the two that were real, the instinct is to upgrade to the latest version. Resist it. The latest version carries every behavioural change since the one you are on, and you are now debugging a feature regression during what was supposed to be a security fix.
Advisories name the first patched version. Go there. If that means a minor bump rather than a major one, the fix ships today with a small diff someone can actually review, instead of next week with a large one nobody reads.
What the triage is really buying
The point is not to make the number smaller. It is to be able to say, with a reason attached, why sixty-one alerts are not being acted on — and to have that reason survive someone asking about it in three months.
A pile of unread alerts is not a security posture. Neither is a green dashboard achieved by upgrading everything on sight. What you want is a short, defensible list, and the record of how it got short.
Two were real. Both were patched the same day.
Tell us what you're building.
A first call is thirty minutes and costs nothing. Bring the thing that is annoying you most — that is usually the fastest way in.
Start a conversation