Skip to content

Base Image CVE Maintenance

Recurring maintenance for the OS-level CVE volume reported by Trivy on the Docker images (SUP-002, 2026-07 security audit). This is a cadence, not an incident response: base images are pinned by digest (reproducible builds) which also freezes their OS CVEs until the digest is bumped.

When to use

  • Scheduled base-image refresh (recommended monthly, or on a published CVE with a fix that affects a package we actually use).
  • Trivy / Dependabot flags a HIGH/CRITICAL on the php, pwa, or provisioner image.

Diagnosis

# Build the prod images: `make build` (php, pwa), plus the profiled provisioner:
#   docker compose -f compose.yaml --profile provisioning build provisioner
trivy image --severity HIGH,CRITICAL bike-trip-planner-php:ci
trivy image --severity HIGH,CRITICAL bike-trip-planner-pwa:ci
trivy image --severity HIGH,CRITICAL bike-trip-planner-provisioner:prod

Read the Status column, not the raw count. The bulk of the volume on the Debian Bookworm bases (perl, python3.x, zlib1g, curl, libssh2, acl, linux-libc-dev, ...) is will_not_fix / fix_deferred / affected — no upstream patch exists, so a rebuild cannot clear them. The actionable subset is only the rows with Status: fixed. Triage those; ignore the won't-fix noise.

Procedure

  1. Bump the digest of the affected base to the latest published for its tag:

    • .docker/php/Dockerfile - dunglas/frankenphp:1-php8.5@sha256:... and dunglas/frankenphp:1-builder-php8.5@sha256:.... Bump both together: the builder stage recompiles the FrankenPHP binary (Mercure protocol 1.0) and its libphp must match the runtime image.
    • .docker/pwa/Dockerfile - node:26@sha256:...
    • .docker/provisioner/Dockerfile - php:8.5-cli-bookworm@sha256:... (three FROM lines, same digest).
    docker pull dunglas/frankenphp:1-php8.5
    docker inspect --format='{{index .RepoDigests 0}}' dunglas/frankenphp:1-php8.5
    
  2. Rebuild and re-scan (the build and Trivy commands above); confirm the fixed-status rows dropped.

  3. Run the full suite (make test) — a base bump can shift a system library.

Verification and follow-up

  • The osmium-tool decision keeps the provisioner on Bookworm (no Alpine migration — osmium has no prebuilt Alpine binary). Distroless is only viable for stages that don't need osmium/osm2pgsql.
  • Note in the PR which fixed CVEs were actually cleared vs. the won't-fix volume that remains by design.