Data
Both datasets are published one file per CVE year, as gzip-compressed CSV and Parquet.
There is no combined "all years" file: the history only grows, and a single file would
eventually break the deploy. Grab the years you need, or loop over all of them (see
Using with dbt or Using with a posture collector
below), or fetch
manifest.json for a machine-readable list of
each table's schema and full file list, keyed by cve_summary and
cve_cpe.
Generated 2026-09-17 21:39:08 UTC.
cve_summary is one row per CVE. cve_cpe is a child table keyed by
cve_id, with one row per CPE match and multiple rows per CVE where a CVE
affects multiple CPEs (see the schema).
๐๏ธ = gzip-compressed CSV ยท ๐ฆ = Parquet
To use a dataset as a dbt seed,
stitch the year files together into your project's seeds/ directory. Rather than
guessing at a year range, fetch manifest.json
and download every file it lists under the table's files.csv, decompressing and
appending each in turn (keeping the header from the first file only). Requires
jq.
table=cve_summary # or cve_cpe
dest="seeds/${table}.csv"
: > "$dest"
for url in $(curl -fsSL https://cve-db.pages.dev/manifest.json | jq -r ".${table}.files.csv[]"); do
if [ -s "$dest" ]; then
curl -fsSL "$url" | gunzip | tail -n +2 >> "$dest"
else
curl -fsSL "$url" | gunzip > "$dest"
fi
done
dbt seed --select "$table"
posture ships
a cve_db collector that reads manifest.json
directly and pulls each table's Parquet files straight into a pandas.DataFrame โ
no download step, no credential (this dataset is public):
from posture import CCM
ccm = CCM("cve_db") # no credentials needed โ public dataset
df = ccm.collect("cve_summary") # or "cve_cpe"
Once you've got the files, see Now What? for worked queries that turn this data into an actual remediation priority list.