Where vulnerability data actually comes from (and why your alerts feel useless)
Every dependency scanner you’ve ever used — npm audit, Dependabot, Snyk, the paste-a-manifest websites — is drinking from the same public well. Once you see the plumbing, two things become obvious: why these tools are all “free,” and why they all exhaust you anyway.
The supply chain of a vulnerability
A vulnerability’s paper trail usually looks like this:
- Someone finds it. A security researcher, a maintainer, occasionally an attacker’s victim. They report it (ideally privately) to the project.
- It gets a CVE. The project or a CVE Numbering Authority requests an identifier from the CVE program — that’s the
CVE-2026-XXXXXstring. The CVE record itself is thin: an ID, a description, references. - NVD enriches it. The US National Vulnerability Database attaches severity scoring (CVSS), affected-product metadata, and links. This is the database most enterprise tools historically queried — and the one whose enrichment backlogs make headlines.
- Ecosystems curate their own. This is the part most developers don’t know. The GitHub Advisory Database curates advisories for npm and friends. Rust has RustSec. Python has the PyPA advisory database. Go has its own vulndb, with reachability analysis built into
govulncheck. These are often faster and more precise than the CVE/NVD path, because they’re maintained by people who live in that ecosystem and they record exact affected version ranges per package. - OSV.dev aggregates everything. Google’s OSV project pulls those ecosystem databases into one schema, keyed by package name and version range, with a free public API anyone can query. When a tool tells you
tokio 1.38 has RUSTSEC-2026-XXXX, there’s a very good chance the answer came from OSV or one of its upstreams.
That’s the well. Nobody owns it. It’s a genuine commons — researchers, maintainers, GitHub, Google, and government infrastructure all feeding one public record. Which leads to the first honest conclusion:
Access to vulnerability data is worth approximately nothing. It’s free, it’s public, and it’s one HTTP call away. Any tool whose pitch is “we know about CVEs” is reselling tap water.
So why do your alerts feel useless?
Because the well gives you facts, and what you needed was judgment. The failure mode of every scanner built on the commons is the same, and it has a name: alert fatigue.
Dependabot is the canonical example, through no fault of its own. It’s on by default for every GitHub repo, it’s thorough, and that’s exactly the problem: thoroughness without context. It cannot know that:
- the vulnerable function is in a code path you never call;
- the affected package is a devDependency that never ships;
- the “critical” finding is in a transitive dep five levels down, pinned by something you can’t upgrade anyway;
- the advisory affects versions you already moved past;
- or that of the 47 open alerts, exactly 2 sit in the hot path of the thing you deploy on Friday.
So it tells you all 47, with equal urgency, forever. Every developer learns the same reflex: mute, batch, ignore. Studies of dependency-alert behavior keep finding the same shape — the majority of alerts are ignorable, so the majority of alerts get ignored, and occasionally one of the ignored ones is the one that mattered. The data was in the well the whole time. The triage never existed.
The second thing the well doesn’t carry
Here’s the gap that bites even teams with disciplined security hygiene: vulnerability databases only contain vulnerabilities. Almost everything else that will ruin your month is not in any of them:
- the breaking change shipping in your framework’s next major;
- the deprecation notice buried in a release note;
- the maintainer who quietly archived the repo your auth flow depends on;
- the license change three dependencies deep;
- the migration window that’s open now and painful later.
That information exists — scattered across release notes, GitHub discussions, changelogs, mailing lists, and the places developers argue. No structured database aggregates it, because it isn’t structured. It’s prose. Reading it all is a full-time job nobody is doing, which is why “we found out from the postmortem” remains the industry’s default discovery mechanism.
What would actually help
Not another scanner. The well is covered. What’s missing sits on top of it:
- Triage against your tree — facts ranked by whether they touch code you actually ship, starting from your real manifests and lockfiles, not a generic severity number.
- Coverage beyond the databases — the unstructured layer (releases, deprecations, discussions, abandonments) read continuously and matched against your stack.
- Continuity — a scan is a photograph; the dangerous window is the time between photographs. Whatever watches has to watch all day.
- Receipts — if a tool claims it surfaces things early, that claim should be independently checkable, with timestamps someone else owns.
That stack of requirements is, not coincidentally, what we build. 4DA reads the internet for developers — privately, locally — and gets sharper every day: the databases above plus the unstructured layer, scored against your actual dependency tree, on your machine. Hold us to the whole list.
You don’t have to take any of that on faith today. The thirty-second version runs in your browser: paste your manifest and see what happened around your stack — advisories, releases, majors you’re behind, deprecations. Your manifest never leaves the page; the only requests are package names to the same public well this article just described. Watch the network tab while it runs.
Try Stack Scan → or give your coding agent the radarOr just keep muting the 47 alerts. One of them is probably fine.