Update Schedule

DevGuard maintains its own aggregated vulnerability database that is rebuilt every 6 hours from upstream sources, cryptographically signed, and distributed as an OCI artifact. DevGuard instances pull these incremental updates automatically.

Build Schedule

The vulnerability database is built by a GitHub Actions workflow that runs on a fixed schedule:

PropertyValue
ScheduleEvery 6 hours (0 */6 * * *)
TriggerCron schedule + manual dispatch
Pipelinevulndb.yaml
Artifact registryghcr.io/l3montree-dev/devguard/vulndb/v1

Data Sources Synced

Each build synchronizes the following upstream sources into a single PostgreSQL database:

SourceDescription
OSVOpen Source Vulnerabilities — covers npm, PyPI, Go, Maven, Cargo, NuGet, RubyGems, and many more ecosystems
EPSSExploit Prediction Scoring System — probability that a CVE will be exploited in the wild
CISA KEVKnown Exploited Vulnerabilities catalog
CWECommon Weakness Enumeration taxonomy
ExploitDBPublic exploit database
GitHub PoCProof-of-concept exploits published on GitHub
Debian Security Tracker (DSA)Debian-specific security advisories and affected package mappings
Malicious PackagesKnown malicious packages across ecosystems

Build Pipeline

The workflow executes the following steps in sequence:

  1. ImportPull the latest published database state from the OCI registry using devguard-cli vulndb import, restoring the previous build as a baseline.
  2. SyncFetch fresh data from all upstream sources using devguard-cli vulndb sync. This updates CVEs, affected components, exploit data, EPSS scores, CISA KEV status, CWE mappings, and malicious package entries.
  3. ExportCompute the differential between the previous and current database states using devguard-cli vulndb export. The result is a set of CSV files containing only inserts, updates, and deletes.
  4. PackageBundle the differential CSV files into a vulndb.zip archive.
  5. SignSign the archive using Cosign with a private key. The signature is stored as vulndb.zip.sig.
  6. PublishPush both the archive and its signature to the GitHub Container Registry as OCI artifacts using ORAS. Each artifact is tagged with a Unix timestamp (e.g., 1708185600).

Distribution Format

The database is distributed as OCI artifacts via the GitHub Container Registry:

ghcr.io/l3montree-dev/devguard/vulndb/v1:<timestamp>         # differential update
ghcr.io/l3montree-dev/devguard/vulndb/v1:<timestamp>.sig      # cosign signature
ghcr.io/l3montree-dev/devguard/vulndb/v1:<timestamp>-snapshot  # full snapshot (periodic)
ghcr.io/l3montree-dev/devguard/vulndb/v1:<timestamp>-snapshot.sig

Each archive contains CSV files with the changes since the last build:

FileContents
cves_insert.csv / cves_update.csv / cves_delete.csvNew, modified, or removed CVE entries
affected_components_*.csvAffected component mappings
cve_affected_component_*.csvCVE-to-component join records
cwes_*.csvCWE taxonomy updates
exploits_*.csvExploit data changes
malicious_packages_*.csvMalicious package entries
malicious_affected_components_*.csvMalicious package component mappings
cve_relationships_*.csvCVE relationship updates

How DevGuard Instances Consume Updates

DevGuard server instances automatically pull and apply database updates:

  1. On startup (and periodically thereafter), the server's VulnDB daemon calls ImportFromDiff.
  2. The daemon connects to ghcr.io/l3montree-dev/devguard/vulndb/v1 and lists all available tags.
  3. It identifies tags newer than the last imported version (tracked in the vulndb.lastIncrementalImport config key).
  4. For each new tag, it downloads the OCI artifact, verifies the Cosign signature against the bundled cosign.pub public key, unzips the archive, and applies the differential CSV files to the local database.
  5. Snapshot tags are handled separatelyif a snapshot is encountered, the full database state is loaded before applying subsequent differentials.

Signature Verification

Every database artifact is signed and verified before being applied:

  • Signing: The build pipeline signs vulndb.zip using Cosign with an ECDSA private key. The signature is base64-encoded and published alongside the archive.
  • Verification: On import, the DevGuard instance loads the cosign.pub public key, downloads the .sig artifact for the corresponding tag, and verifies the signature using sigstore/sigstore. If verification fails, the update is rejected.

This ensures that only database artifacts built by the official pipeline are applied, protecting against supply chain attacks on the vulnerability data itself.