Skip to content

Graphic preview

100%
Page type: how-to

Scan database versions for known vulnerabilities

Match a self-managed database version against pinned local server advisories.

Edge documents the current development build and may describe unreleased behavior. To use those commands, build Ptah from master. For an installed release, select its version in the header.

ptah db vulnerabilities reads the product and version of a live database and matches them against a pinned local server advisory snapshot. You can run it in CI without a Ptah account or an advisory service. The scan reads the database and the local snapshot; it does not upload inventory.

This check answers whether a known advisory’s version range matches the observed server. ptah schema security checks roles, grants, ownership, and policies instead. A clear result from either command is limited to what that command assessed.

You need an installed ptah binary and a database URL. The default --deployment self-managed means your team controls server patching. For PostgreSQL, the connected role also needs to read pg_catalog.pg_extension. The command reads the version banner; PostgreSQL also reads the numeric server version and extensions in the connected database. It does not change the database.

Terminal window
ptah db vulnerabilities --db-url "$DATABASE_URL"

The table report names each affected or uncertain advisory, its component, installed server version, advisory URL, CVSS score when supplied, and known fix. It also lists gaps and summarizes fixed and unaffected matches. The --format json report keeps every assessment, including fixed and unaffected ones, plus the inventory, source identity, and incomplete coverage.

Terminal window
ptah db vulnerabilities --db-url "$DATABASE_URL" --format json > vulnerabilities.json

The JSON source block includes the upstream URL, a SHA-256 of the source page, a SHA-256 of the normalized snapshot, retrieval time, age in days, and current, stale, or unavailable. The assessments array uses affected, fixed, unaffected, or uncertain. The separate incomplete array names coverage gaps. applicability distinguishes assessed, unassessed, and not_applicable. Failed snapshot input or database inventory produces a scan_error in JSON and exits with code 2.

If a provider operates the server, select --deployment managed. The report records not_applicable, makes no advisory assessment, and does not fail the default CI policy. This override works for every engine, including YDB. Use self-managed when your team controls the server version, even if it runs in a cloud account. Ptah does not infer patch responsibility from the endpoint.

Terminal window
ptah db vulnerabilities --db-url "$DATABASE_URL" --deployment managed --format json

The default --fail-on both exits 1 for an unsuppressed affected advisory or incomplete coverage. Select findings, incomplete, or none when your gate needs a different policy. Input and connection failures exit 2 under every policy.

Terminal window
ptah db vulnerabilities --db-url "$DATABASE_URL" --fail-on both --format json

To accept one affected advisory temporarily, write a local JSON suppression file. Its ID, product, component, and reason are required. An expiry is optional. An expired or invalid suppression fails the scan. Suppressed assessments remain in the JSON report with the reason.

[
{
"id": "CVE-2026-18024",
"product": "postgres",
"component": "core",
"reason": "Vendor patch verified in change ticket SEC-42",
"expires": "2026-12-31"
}
]
Terminal window
ptah db vulnerabilities --db-url "$DATABASE_URL" --suppressions suppressions.json

The engine declares whether Ptah can match its server version. Ptah bundles the built-in engine snapshots. The YDB provider bundles its own snapshot:

Engine Reviewed source Coverage
PostgreSQL PostgreSQL security page Core and selected bundled modules on listed upstream release lines.
YDB provider YDB security changelog The provider owns server entries; the Go SDK entry is outside server scope.
MariaDB Community Server CVE list Three selected server CVEs; the report remains incomplete.
ClickHouse Security changelog One selected server CVE on four release lines; the report remains incomplete.

A provider that declares scanning but supplies no reviewed snapshot returns unassessed unless --advisories selects a local source.

The PostgreSQL snapshot names its supported lines in release_lines. It matches core advisories and entries naming pgcrypto, pg_trgm, intarray, or refint. Their fixes ship with the server minor release: extversion records the installed module, not its patch level. The extension catalog covers only the connected database. Client-only advisories are excluded.

DuckDB and Spanner declare a server scan not_applicable: DuckDB is embedded, while Spanner is a managed service. SQLite returns unassessed because a libsql:// address can reach a remote server. Other built-in engines without a reviewed matcher also return unassessed. An unsupported release line, vendor build, or unrecognized version remains uncertain because a distribution may backport a fix. Version matching also cannot establish whether a vulnerable code path is reachable. Investigate the linked advisory and your vendor’s patch record before deciding how to remediate.

The snapshot becomes stale 30 days after retrieval. A stale snapshot remains visible in the report and counts as incomplete coverage. Refresh it before using an empty finding list as a current assessment.

The daily Server advisory snapshots workflow in Ptah checks PostgreSQL, MariaDB, and ClickHouse. The YDB provider runs its own daily source check and bundles the reviewed result in its executable. Both workflows open a draft pull request when a snapshot needs a refresh. PostgreSQL rows are parsed and validated before the snapshot is written. An unchanged versioned source can refresh its retrieval time after 14 days.

The YDB provider records both the raw documentation hash and the advisory body hash. A changed documentation revision outside the advisory body creates no review report. A changed advisory body produces a JSON report in the provider’s internal/vulnerability/review/ directory. The report lists observed CVE IDs and source hashes; it does not establish affected ranges.

Verify server CVEs, affected starts, fixed versions, and release lines before updating a snapshot. Remove its review report before merging. Partial coverage remains partial until the reviewed snapshot covers more advisories.

To run the daily source check locally, use:

Terminal window
go run ./internal/cmd/securitysnapshots

From a source checkout, run the updater and review the JSON diff:

Terminal window
go run ./internal/cmd/pgsecuritysnapshot
git diff -- internal/vulnerability/postgresql.json

The updater fetches the PostgreSQL security page and records its source digest and retrieval time. Use -input saved.html to parse a saved copy without network access. It refuses missing headings, table columns, affected/fixed mismatches, unknown components, and empty coverage. The scan itself never fetches advisories. You can select a reviewed local JSON file with --advisories path/to/snapshot.json.

Review newly named components, release-line changes, and the advisory source before committing an update. The snapshot derives from PostgreSQL’s published security information under the PostgreSQL License. The source link, digest, and license notice travel with the snapshot in the repository.

An installed Ptah binary carries the built-in snapshots. A provider executable carries its own snapshot. Update the relevant binary or use --advisories to select another reviewed local file. For a versioned engine, the snapshot uses schema version 2. Review each affected start, fixed version, release line, and CVE source before updating its JSON in the owning repository. Pin the upstream page’s SHA-256 and retrieval time. Set coverage to partial with a reason when the snapshot omits advisories; the scanner then reports incomplete coverage. A source URL or hash alone does not prove that its affected ranges were reviewed.