how to automate CVE notification triage
A skill for building automated CVE notification triage: pulling from OSV, NVD, and the CISA exploited list, deduping by CVE ID, filtering against your inventory, and routing alerts by real urgency. Use when CVE emails and scanner noise exceed what a human can triage. Triggers: 'CVE automation', 'vulnerability feed triage', 'CVE alert fatigue'. Not for: triaging a single CVE by hand, writing the leadership summary.
how to automate CVE notification triage
TL;DR
Pull CVE feeds into one normalized list keyed by CVE ID, filter it against the software you actually run, and route only the exploited or reachable ones to a human. Everything else goes to a digest or gets suppressed with a logged reason. Automation does not decide patching; it decides what deserves a human's attention.
how to automate CVE notification triageUse this when
- CVE notifications from scanners, vendors, and mailing lists exceed manual triage capacity
- The same CVE arrives from three sources and gets triaged three times
- You want exploited-in-the-wild CVEs to page someone within hours
- Leadership wants a defensible, repeatable intake process
Not for this skill when
- You are triaging one specific CVE right now (triage it by hand, that is faster)
- You have no inventory of what you run (build that first; filtering needs it)
- You need the executive summary format (different skill, different audience)
Steps
1. Pick your sources and one key
Use the OSV API for dependency-level matches, NVD for breadth, and the CISA known-exploited catalog for the page-worthy set. Key every record by CVE ID so duplicates collapse.
curl -s "https://api.osv.dev/v1/querybatch" -X POST -H "Content-Type: application/json" --data "[request-body]"Expected: a JSON response with vulnerability records per queried package. Build the request body from your lockfiles; the exact shape is in the OSV API docs. NVD and CISA each get their own fetcher writing into the same normalized table.
2. Normalize into a single queue
Map every source into the same fields: CVE ID, product, affected versions, fixed version, severity, published date, and exploitation signal. Dedupe on CVE ID, keeping the richest record.
Expected: one row per CVE, no duplicates. If the same CVE still appears twice, your key is wrong; check for whitespace or case differences in the ID.
3. Filter against your real inventory
Drop anything whose product and version range does not match what you run. This is the step that kills most of the noise.
Expected: the queue shrinks dramatically, often by 80 percent or more. Everything filtered out gets logged with the reason, so the decision is auditable later.
4. Route by urgency, not by severity score
Route rules that work: on the CISA exploited list goes to the on-call channel immediately; critical severity plus reachable code path goes to the security queue same-day; everything else goes to the weekly digest.
Expected: pages stay rare and meaningful; the digest stays skimmable. If the on-call channel fires more than a couple of times a month, your routing is too loose.
5. Keep a suppression log with reasons
False positives and accepted risks get suppressed by rule, each with a reason and an expiry date. Suppressions auto-expire so nothing is ignored forever.
Expected: a suppression list you can show an auditor. No expiry on suppressions is how real vulns hide for years.
Variant: dependabot alert flood specifically
Route Dependabot PRs through the same queue: auto-merge patch-level bumps with passing tests, batch minor bumps weekly, and only hand-triage majors and anything the scanner marks reachable.
Variant: weekend zero-day intake
The exploited-list fetcher runs on a short interval and pages directly, bypassing the digest. One narrow rule, tested monthly with a synthetic entry, beats a general "watch everything" job.
Why this happens
Every scanner and feed speaks a different schema and has a different opinion of severity, so humans end up re-normalizing the same CVE in their heads repeatedly. A single normalized queue with inventory filtering moves that normalization into code, which is consistent and never gets tired.
Edge cases and pitfalls
- Transitive dependencies: your inventory must include the full dependency tree, not just direct deps.
- Feeds disagree on version ranges: keep the union and note the conflict rather than picking one blindly.
- Embargoed or brand-new CVEs lag in NVD by hours; the vendor advisory is the early source.
- Over-suppression: expiring suppressions and quarterly reviews keep the list honest.
- Alerting on CVSS alone pages people for unreachable criticals while missing exploited mediums; exploitation signal must outrank the score.
Provenance
Resolved from the public thread: https://vectle.com/posts/pst5eakrh7XcRzv-ZelsB1RA
Maintainer review
No maintainer verification is recorded for this version.
This records the version a maintainer checked. It does not assert that the version is the latest upstream release.