Putting it to work
DuckDB can read the gzip-compressed
year files directly, with no download or unzip step required. Install it, then load every year
straight from this site into a single table. Every query below assumes this
cve table has already been created — run this first.
INSTALL httpfs;
LOAD httpfs;
CREATE TABLE cve AS
SELECT *
FROM read_csv_auto([
'https://cve-db.pages.dev/cve_summary_1999.csv.gz',
'https://cve-db.pages.dev/cve_summary_2000.csv.gz',
'https://cve-db.pages.dev/cve_summary_2001.csv.gz',
'https://cve-db.pages.dev/cve_summary_2002.csv.gz',
'https://cve-db.pages.dev/cve_summary_2003.csv.gz',
'https://cve-db.pages.dev/cve_summary_2004.csv.gz',
'https://cve-db.pages.dev/cve_summary_2005.csv.gz',
'https://cve-db.pages.dev/cve_summary_2006.csv.gz',
'https://cve-db.pages.dev/cve_summary_2007.csv.gz',
'https://cve-db.pages.dev/cve_summary_2008.csv.gz',
'https://cve-db.pages.dev/cve_summary_2009.csv.gz',
'https://cve-db.pages.dev/cve_summary_2010.csv.gz',
'https://cve-db.pages.dev/cve_summary_2011.csv.gz',
'https://cve-db.pages.dev/cve_summary_2012.csv.gz',
'https://cve-db.pages.dev/cve_summary_2013.csv.gz',
'https://cve-db.pages.dev/cve_summary_2014.csv.gz',
'https://cve-db.pages.dev/cve_summary_2015.csv.gz',
'https://cve-db.pages.dev/cve_summary_2016.csv.gz',
'https://cve-db.pages.dev/cve_summary_2017.csv.gz',
'https://cve-db.pages.dev/cve_summary_2018.csv.gz',
'https://cve-db.pages.dev/cve_summary_2019.csv.gz',
'https://cve-db.pages.dev/cve_summary_2020.csv.gz',
'https://cve-db.pages.dev/cve_summary_2021.csv.gz',
'https://cve-db.pages.dev/cve_summary_2022.csv.gz',
'https://cve-db.pages.dev/cve_summary_2023.csv.gz',
'https://cve-db.pages.dev/cve_summary_2024.csv.gz',
'https://cve-db.pages.dev/cve_summary_2025.csv.gz',
'https://cve-db.pages.dev/cve_summary_2026.csv.gz'
]);
For anything reachable from the internet, prioritise CVEs that are exploitable remotely, without needing valid credentials first:
SELECT cve_id, published, base_severity, base_score, product, cwe
FROM cve
WHERE is_remote = 1 -- attack vector: network
AND requires_auth = 0 -- no credentials needed
AND base_severity IN ('HIGH', 'CRITICAL')
ORDER BY base_score DESC, published DESC;
For end-user workstations on an internal network, the realistic threat is usually a user being tricked into clicking something, so filter for CVEs that need local or adjacent access and some form of user interaction:
SELECT cve_id, published, base_severity, base_score, product, cwe
FROM cve
WHERE (is_local = 1 OR is_adjacent = 1)
AND requires_user_interaction = 1 -- a user has to click/open something
AND base_severity IN ('HIGH', 'CRITICAL')
ORDER BY base_score DESC, published DESC;
The "drop everything" list: known exploitation in the wild, and nowhere to point a fix yet.
SELECT cve_id, published, base_severity, base_score, product, cwe
FROM cve
WHERE ssvc_exploitation = 'active'
AND has_patch_reference = 0
ORDER BY base_score DESC, published DESC;
No credentials, no user interaction, and automatable at scale: the classic self-propagating worm profile.
SELECT cve_id, published, base_severity, base_score, product, cwe
FROM cve
WHERE is_remote = 1
AND requires_auth = 0
AND requires_user_interaction = 0
AND ssvc_automatable = 'yes'
ORDER BY base_score DESC, published DESC;
Group by product to spot which vendor or platform you run is racking up the most, and the most severe, unresolved CVEs:
SELECT product, COUNT(*) AS cve_count, MAX(base_score) AS worst_score
FROM cve
WHERE base_severity IN ('HIGH', 'CRITICAL')
GROUP BY product
ORDER BY cve_count DESC
LIMIT 20;
A patch exists, the severity is critical, and it's still open after 90 days: a process failure, not a data gap.
SELECT cve_id, published, base_severity, base_score, product, cwe
FROM cve
WHERE base_severity = 'CRITICAL'
AND has_patch_reference = 1
AND published < now() - INTERVAL 90 DAY
ORDER BY published ASC;
Hardware you deploy in physically accessible locations (kiosks, ATMs, badge readers) has a different threat model again, so prioritise CVEs that require only physical access:
SELECT cve_id, published, base_severity, base_score, product, cwe
FROM cve
WHERE is_physical = 1
AND base_severity IN ('HIGH', 'CRITICAL')
ORDER BY base_score DESC, published DESC;