Vulnerability Management

CVE Triage Is Broken. Here's a Better Workflow.

Most enterprise CVE queues are noise. KEV plus EPSS plus reachability plus policy-as-code cuts the real actionable list to a manageable few percent.

Shadab Khan
Security Engineer
7 min read

The average mid-sized enterprise sees 3,000 to 8,000 open CVEs across its scanned estate in any given week. The average security team has between three and twelve people who can action them. The math does not work. What security teams have learned, and what most vulnerability management programs have still not institutionalized, is that CVSS-only triage was never the right frame. Most of those CVEs are not exploitable in your context. A small fraction are. The job is separating those two groups programmatically, not with human eyes on a spreadsheet.

2025 reinforced this. NVD published 41,812 CVEs in 2025, a 28% increase over 2024. CISA's Known Exploited Vulnerabilities catalog added 188 entries in the same period. The ratio is roughly 1 in 222. If your program treats every CVE with CVSS 7.0+ as a P1, you are burning analyst time on exploits that will never land in your environment while under-weighting the ones already being used against you.

Why Is CVSS Alone Misleading?

CVSS is misleading because it scores the vulnerability, not the risk to your specific system. A CVE with CVSS 9.8 in a library loaded by your code but never called from any reachable path is not a 9.8 risk. A CVE with CVSS 5.3 in a parser on your internet-facing boundary with active exploitation in the wild may be the highest priority item in your queue that morning.

The specific failure modes of CVSS-first triage:

  • No exploitation signal. CVSS reflects theoretical severity. It does not reflect whether exploits exist, whether they are in the wild, or whether your threat model actors use them.
  • No reachability. CVSS has no concept of whether the vulnerable function is reachable from your application's entry points. Many CVEs sit in code paths your service does not exercise.
  • No environmental modeling. The Environmental metrics in CVSS 3.1 are intended to adjust for deployment context, but almost no teams compute them at scale because the inputs are expensive to produce by hand.
  • Inflation bias. Research from FIRST and others shows CVSS v3.1 scores cluster toward the 7.0-9.8 band because scorers favor worst-case AV:N/AC:L assumptions when evidence is ambiguous.

CVSS v4.0 improves some of this with Threat and Environmental groups, but adoption is still partial. In practice, CVSS v4 scores in your queue will sit next to CVSS v3.1 scores for the foreseeable future. The fix is to treat CVSS as one signal among several, not the ranking key.

What Does a Workable Triage Workflow Look Like?

A workable workflow applies four filters in sequence, each cheaper than the next and each cutting the list by roughly an order of magnitude. The model that works for most teams:

Step 1: KEV and EPSS filter. Start by flagging every CVE in CISA KEV and every CVE with an EPSS score above 0.3. EPSS estimates the probability a CVE will be exploited in the next 30 days based on empirical signals. A 0.3 threshold captures the top decile of likely-exploited vulnerabilities and is the threshold CISA uses in its own guidance. This single filter typically reduces a 5,000-CVE queue to 150-400 candidates.

Step 2: Reachability analysis. For the remaining candidates, determine whether the vulnerable function is reachable from your application's execution entry points. Reachability analysis parses your codebase, resolves call graphs through direct and transitive dependencies, and asserts yes or no for each CVE. Industry data from Endor Labs, Semgrep, and our own deployments consistently shows 60-80% of CVEs in open-source dependencies are not reachable from application code. The remaining 40-60 CVEs for a typical service are your actionable list.

Step 3: Policy-as-code evaluation. Apply organization-specific rules to the reachable set. Example policies: "CVEs in auth-critical services require a fix within 7 days regardless of score," "CVEs in sandboxed workers can wait for the next release cycle unless KEV-listed," "CVEs requiring authenticated access to exploit are lower priority for internal-only services." These rules live in a repo, get reviewed by security and engineering together, and produce deterministic outputs. This typically halves the actionable list again.

Step 4: Exception workflow with expiry. Anything your team cannot patch immediately enters an exception workflow. Exceptions require a compensating control, an owner, and an expiry date (commonly 30, 60, or 90 days depending on severity). Expired exceptions generate tickets. The absence of an expiry discipline is the top reason vulnerability programs drift - unremediated CVEs become invisible background noise.

What Concrete Numbers Should You Expect?

A well-tuned pipeline using this workflow produces predictable ratios. From recent Safeguard deployments and public numbers from Kusari, Endor, and the Snyk 2025 State of Open Source Security:

  • Initial scan on a typical mid-sized service: 2,000-6,000 CVEs across direct and transitive dependencies.
  • After KEV + EPSS > 0.3 filter: 80-300 CVEs remain (95% reduction).
  • After reachability analysis: 20-80 CVEs remain (further 60-80% reduction).
  • After policy-as-code evaluation: 10-40 CVEs require human action in the current cycle.
  • After exception workflow: 5-20 CVEs get patched this sprint, the rest have owners and expiries.

A small security team can action 10-40 real CVEs per week across a portfolio. It cannot action 5,000. The workflow is not about working harder. It is about forcing honesty about what actually matters.

How Do You Avoid Under-Remediating Real Issues?

You avoid it by building explicit feedback loops on the filters, not by widening them back out. The common failure is "what if reachability gets it wrong." The right answer is measuring that error rate and tuning to it, not discarding the filter.

Practical controls:

  • Reachability false-negative monitoring. When a CVE is later proven exploitable in your environment, trace back to whether reachability flagged it. Maintain a dashboard showing this rate over time. A mature pipeline runs below 2% false negatives on reachability.
  • KEV-on-entry alerting. When a CVE enters CISA KEV, re-evaluate immediately regardless of prior filter verdicts. KEV entry is the highest-signal event in the public vulnerability data.
  • Exception audit cadence. Monthly review of open exceptions. Any exception older than 90 days without active remediation progress escalates to engineering leadership.
  • Threat-informed overrides. When threat intelligence indicates your sector or tech stack is being targeted, raise the aggressive-patch threshold for that scope temporarily. This is where human judgment belongs, not in initial triage.

The philosophical shift is that "patch everything" was never achievable, and pretending otherwise produced a queue nobody actioned. The goal is a queue small enough to action completely, plus explicit exceptions you review.

Where Does This Break Down?

It breaks down when your dependency tree is not accurate or your exploitability data is stale. If your SBOM misses transitive dependencies, reachability analysis is analyzing the wrong graph. If EPSS is stale, filter decisions are made on week-old probabilities. If policy-as-code is not version-controlled, nobody knows what yesterday's rule was. The workflow assumes good inputs, and most of the failures we see in the field trace to one of these input problems rather than the workflow itself.

The other common break is alert fatigue recovery time. Teams coming off a CVSS-firehose posture often keep noise handlers ("ignore if CVSS < 7") even after switching to the better workflow. Those handlers mask the new signal. The workflow works cleanly only when the queue is genuinely small enough to take seriously.

How Safeguard.sh Helps

Safeguard.sh implements this exact workflow end-to-end. We generate and ingest SBOMs with 100-level dependency depth scanning so the graph reachability runs against is complete, not just your top-level imports. Reachability analysis cuts 60-80% of CVE noise before any human sees it, and the remaining set is filtered through your policy-as-code rules with KEV and current EPSS data. Griffin AI then autonomously opens remediation PRs for the actionable CVEs and coordinates container self-healing for runtime-hot fixes that cannot wait for a deploy cycle. Exceptions are first-class objects with owners, compensating controls, and expiries that re-fire as alerts when they lapse. The TPRM module runs the same triage logic against your vendors so their CVE posture shows up in your program as structured risk rather than a PDF you file and forget.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.