Dev.to Security πŸ” Cybersecurity πŸ‘ 0 πŸ“– 2 min read

Stop triaging CVEs that never touch your code

Every serious engineering org runs some form of software composition analysis. And almost every one of them has the same quiet failure mode: the scanner reports dozens of β€œhigh” findings, half of them are in development

Every serious engineering org runs some form of software composition analysis. And almost every one of them has the same quiet failure mode: the scanner reports dozens of β€œhigh” findings, half of them are in development tooling nobody imports, a few sit in transitive packages two layers down, and the team learns to click β€œdismiss” until a real issue slips through.

Dan Abramov wrote the definitive autopsy years ago β€” npm audit is broken by design β€” and the industry still mostly ships package-presence scanners. Presence is not risk.

What actually determines urgency

When I watch security and platform teams work a backlog, five questions decide the outcome:

  1. Is this version known-vulnerable? (OSV / advisories)
  2. Is it being exploited, or likely to be? (CISA KEV, FIRST EPSS)
  3. Does our code load the package at all? (import / require graph)
  4. Is it production or development? Direct or transitive?
  5. Is there a fixed version we can move to without drama?

Commercial SCA platforms answer some of these β€” especially reachability β€” behind a paywall. Free tools often stop at (1). That gap is where person-weeks go to die.

Introducing vulntriage

vulntriage is an open-source CLI and library that answers all five, then emits a decision you can put in a PR comment:

Decision Meaning
FIX NOW High risk and reachable, or KEV on a production path
FIX SOON Material risk β€” schedule the upgrade
MONITOR Low urgency; re-check if usage or EPSS moves
LIKELY NOISE Unimported / dev-only / low exploit signal

Every score lists its factors. No model weights to mystify a review:

FIX_SOON     66   [email protected]
             CVE-2021-23337 Β· EPSS 22.41% Β· imported Β· direct/production
             Β· CVSS 8.1 (HIGH) β†’ +28
             Β· EPSS 22.41% (p97) β†’ +13
             Β· Package is imported in project source β†’ +12
             Β· Direct dependency β†’ +4
             Β· Production dependency β†’ +5
             Β· Fix available (4.18.0) β†’ +3

And the counter-example that makes the tool worth running:

LIKELY_NOISE  0   [email protected]
             CVE-2017-20165 Β· HIGH CVSS Β· not_imported Β· development
             Β· Package is NOT imported in project source β†’ βˆ’25
             Β· Development-only dependency β†’ βˆ’15

Same class of CVSS β€œHIGH.” Completely different action. That is the whole product.

How it works

  1. Parse lockfiles: package-lock.json, pnpm-lock.yaml, yarn.lock, requirements.txt, poetry.lock, Pipfile.lock.
  2. Batch-query OSV for known vulns.
  3. Enrich CVEs with EPSS and the CISA KEV catalog.
  4. Walk project sources and build an import index (JS/TS + Python).
  5. Score, decide, report (table / markdown / JSON / SARIF).

No API keys. No SaaS. Node 18+.

Try it

npx vulntriage .
vulntriage --format sarif -o report.sarif --fail-on fix_now
vulntriage --verbose --no-dev

What comes next

  • Deeper function-level reachability when OSV provides vulnerable symbols
  • Go and Rust ecosystem reachability
  • GitHub Action polish and monorepo configs
  • Baseline / suppressions file with expiry dates (not eternal ignores)

If this saves your team one noisy afternoon, open an issue with a lockfile story that still hurts β€” that is the best way to make the prioritizer better.

πŸ“° Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes β€” full credit and traffic to the original publisher.