Data
Both tables are published as numbered, gzip-compressed CSV pages, sorted so the most recently modified CVEs come first. A new page starts whenever a file approaches the deploy size limit, so the number of pages grows with the data. Start from manifest.json: it lists every page for each table, in order, so your code never has to guess how many exist (see Manifest). Generated 2026-11-02 07:56:18 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).
Read the manifest, then fetch and decompress each page it lists for a table. Requires
requests.
import csv
import gzip
import io
import requests
ENDPOINT = "https://cve-db.pages.dev"
manifest = requests.get(f"{ENDPOINT}/manifest.json").json()
rows = []
for url in manifest["cve_summary"]["files"]["csv"]: # or "cve_cpe"
data = gzip.decompress(requests.get(url).content).decode("utf-8")
rows.extend(csv.DictReader(io.StringIO(data)))
print(len(rows), "rows")
To use a dataset as a dbt seed,
stitch the pages together into your project's seeds/ directory. Rather than
guessing at a page count, 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"
If you already use posture,
its cve_db collector does the same thing for you: it reads
manifest.json and loads a table's pages into a
pandas.DataFrame. No credentials are needed, because the 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.