Security Concepts

Is the Postgres Docker Image Safe? What Our Scanner Found

Published July 8, 2026 · 6 min read

Postgres is one of the most-deployed database images on Docker Hub, so “is the postgres Docker image safe” is worth answering with data instead of assumptions. We scanned postgres:17 and its Alpine variant with ScanRook and looked at what the findings actually mean.

Is the postgres Docker image safe — container image safety series

The verdict

Mostly yes, with caveats. The Postgres project ships timely fixes for the database engine itself, and CVEs in Postgres proper are relatively rare compared to the finding count you see on a full scan. The bulk of that count comes from the Debian base image underneath — GnuPG, dirmngr, and the rest of the userland required to verify and install packages during the build. The practical risks are running an oversized tag when a slimmer one would do, skipping rebuilds after base image patches ship, and giving the database container more privilege than it needs. All three are addressable without touching your schema.

What we found scanning postgres:17

We exported the image with docker save and scanned it with ScanRook, which matches every installed package against OSV, NVD, and vendor advisory data. Here is the severity breakdown for the default Debian-based tag and the Alpine variant:

TagTotalCriticalHighMediumLow
postgres:172,9833879701,344241
postgres:17-alpine410361941689

ScanRook v1.14.2, warm-cache scan, 2026-07-04. Counts change as new advisories publish.

Grouped bar chart of ScanRook severity counts. postgres:17: 2,983 findings total, 387 critical, 970 high, 1,344 medium, 241 low. postgres:17-alpine: 410 findings total, 36 critical, 194 high, 168 medium, 9 low.postgres:172,983 findings totalCritical387High970Medium1,344Low241postgres:17-alpine410 findings totalCritical36High194Medium168Low9
The same scan data as a chart — ScanRook v1.14.2 warm-cache scan of postgres:17 and postgres:17-alpine, 2026-07-04. Bar length is proportional to the count in each severity bucket, on a scale shared by both tags; the figure beside each tag name is the total finding count that scan reported.

As with most Debian-based official images, the headline number is dominated by the base operating system rather than the application. postgres:17 ships GnuPG and its dirmngr helper for signature verification, plus a broad set of Debian utilities, and each contributes its own advisory history. The Alpine tag strips almost all of that away, which is why it carries roughly 86% fewer findings.

The CVEs worth knowing about

The top critical findings from our scan of postgres:17 cluster around three packages:

  • dirmngr — CVE-2005-2023 and CVE-2006-6235.dirmngr is GnuPG's network-facing helper for fetching keys and checking certificate revocation. Both advisories date to the mid-2000s. dirmngr only runs when Postgres's package manager needs to verify a signature, which in a running database container is effectively never — it matters at build time, not at query time.
  • gnupg — CVE-2005-2023 and CVE-2006-6235.Same advisories, flagged against the core GnuPG binary that dirmngr depends on. It ships in the image because Debian's package tooling uses it to verify APT repository signatures during builds and rebuilds.
  • gnupg-l10n — CVE-2005-2023.The localization data package for GnuPG. It carries the same advisory as its parent binary but contains no executable code of its own — it is translation strings, not attack surface.

None of these touch the Postgres server process itself. They are a byproduct of Debian's package-verification chain being present in the image. Our guide to installed-state scanning vs. advisory matching covers why scanners flag decades-old build tooling like this at all.

Which tag should you use?

For most deployments, postgres:17-alpine is the better default. Same upstream Postgres release, same initialization scripts and environment variables, but 410 findings instead of 2,983 and 36 critical instead of 387 in our scan. The tradeoff is musl libc instead of glibc, which occasionally affects extensions compiled against glibc-specific behavior.

Stay on the Debian-based tag if you depend on extensions distributed only as glibc binaries, or your organization standardizes on Debian for compliance tooling. Either way, pin an exact version rather than tracking a floating tag. For the broader tradeoffs between base image families, see Alpine vs Debian vs Distroless.

Hardening checklist

  • Run the container as the built-in non-root postgres user rather than overriding it to root.
  • Pin the image by digest (postgres@sha256:…), not just by tag, so restores and redeploys are reproducible.
  • Store credentials via POSTGRES_PASSWORD_FILE or a secrets manager instead of plain environment variables.
  • Mount the data directory on a dedicated volume with restrictive host permissions.
  • Restrict network exposure — bind to an internal network and avoid publishing 5432 publicly.
  • Rebuild and redeploy on a schedule so base image patches actually reach your running containers.
  • Scan every build in CI so a base image regression is caught before it ships.

Scan it yourself

Counts drift as new advisories publish, so verify against the exact tag and digest you deploy:

curl -fsSL https://scanrook.io/install.sh | sh
docker save postgres:17 -o postgres.tar
scanrook scan postgres.tar

The full CLI reference, including JSON output and severity gating for CI, is in the docs.

Frequently asked questions

Is the postgres Docker image safe to use?

Broadly yes. Postgres itself is patched quickly; most findings come from the Debian base packages underneath it. Use the Alpine tag, pin versions, and rebuild regularly to address the bulk of the practical risk.

Why does the image have so many vulnerabilities?

The default tag ships GnuPG, dirmngr, and a full Debian userland for package verification. Scanners report the whole operating system layer, not just the Postgres binaries.

Is postgres:alpine more secure?

It has a much smaller attack surface: 410 findings vs 2,983 in our scan, about 86% fewer, because musl libc and BusyBox replace the full Debian userland.

Do I need to fix every reported CVE?

No. Triage by severity and reachability — GnuPG and dirmngr never execute in a running Postgres container. A smaller base tag removes whole categories of findings at once.

Scan your postgres image with ScanRook

Upload your image tar or scan from the CLI and ScanRook matches every installed package against OSV, NVD, and vendor advisory data — with severity, exploit-probability, and confidence tiers so you can separate real runtime risk from build-time noise.

Related Posts

More on this topic.