Skip to content

Understanding CVE Database Management

Why meta-tolomeo actively manages the NVD CVE database, and the strategy behind it.

The problem

cve-check scans every recipe against a local copy of the NVD database. The stock cve-update-nvd2-native recipe keeps that copy in ${DL_DIR}/CVE_CHECK and, on later builds, either skips the update (when the file is younger than CVE_DB_UPDATE_INTERVAL) or performs a fast incremental update covering only the days since the last fetch.

The weak point is the first fetch: a full download is slow and, because the public NVD API is rate-limited and occasionally unavailable, it can hang or fail. This happens on every build that starts from an empty downloads directory — CI feature-branch pipelines (which use a one-shot, workspace-local cache) and fresh local checkouts.

meta-tolomeo addresses this with two cooperating mechanisms plus a per-branch policy.

Backup seed

A .bbappend for cve-update-nvd2-native seeds the database from CVE_DB_BACKUP_FILE before the stock fetch runs. When the local database is missing, the backup is copied into place, so the fetch finds a database and only needs a quick incremental update — or skips entirely.

The seed is deliberately conservative:

  • It copies only when the local database is missing, never clobbering an already-cached copy.
  • When the backup path is the build's own database (stable/production builds that write the shared cache), the seed is skipped and the stock update runs in place — the backup is never tainted.
  • If the backup is absent, the build logs a warning and falls back to the normal fetch.

The copy preserves the backup's modification time, so the stock recipe still sees the true age of the data when choosing between skip, incremental, and full re-download.

Scheduled refresh

A seed is only as fresh as its backup. A dedicated CI job refreshes the shared database on a schedule, independent of build cadence, by running the fetch against the shared cache with CVE_DB_UPDATE_INTERVAL=0. Because the shared cache is exactly the default CVE_DB_BACKUP_FILE, every other build seeds from an up-to-date database.

Per-branch update policy

With the shared database kept fresh, each build type chooses how much work to do at build time:

Build type CVE_DB_UPDATE_INTERVAL Rationale
Scheduled refresh 0 Force an incremental refresh of the shared database every run.
Feature build -1 Seed and skip the update — zero network, CVEs still evaluated against the fresh seed.
Production / stable default (86400) Update the shared database in place — a self-healing safety net if the schedule lags.

Feature builds get fast, fresh CVE evaluation with no NVD traffic, while production builds never depend solely on the schedule. Skipping (-1) requires a database to be present; if both the seed source and the local database are missing, the build fails rather than scanning against no data.

See also