Skip to content

fix(docker): patch OS packages in digest-pinned images so releases are not blocked by unpatchable bases #1702

Description

@FelixTJDietrich

The v0.75.0 release was blocked by four HIGH CVEs in the webapp image. The cause is structural, not a stale pin.

The defect

webapp/Dockerfile pins FROM nginx:stable-alpine@sha256:97d490c… and runs apk add --no-cache bash sed grep curl with no apk upgrade. Alpine shipped openssl 3.5.8-r0 and expat 2.8.4-r0; neither can reach the image by any path that exists in this repository:

  • Renovate updates a digest only when upstream publishes a new one. nginx:stable-alpine still resolves to that exact digest today.
  • docker-library documents that Alpine-based official images are "subject to their own maintenance schedule" and rebuilds cascade only to currently-listed tags.

So OS packages in every digest-pinned image here are unpatchable by construction. Verified: that digest carries 4 HIGH; adding apk upgrade --no-cache takes it to 0.

Package CVE Installed Fixed in
libcrypto3, libssl3 CVE-2026-14456 3.5.7-r0 3.5.8-r0
libexpat CVE-2026-66046, CVE-2026-76641 2.8.2-r0 2.8.4-r0

Scope

  • webapp/Dockerfileapk upgrade --no-cache ahead of the existing apk add.
  • docker/agents/pi/Dockerfilethe identical latent failure: digest-pinned node:*-slim, apt-get install, no upgrade. It would block the release after this one. Fix it in the same change.
  • docker/postgres/Dockerfile — the tag floats, so it picks up docker-library rebuilds. Lower priority; add for consistency.
  • Worth 60 seconds first: security/release-images.json already tracks a newer nginx-alpine digest (sha256:db35bfc6…) than webapp/Dockerfile pins. Scan it — if clean, repoint the base as well.

There is no reproducibility trade-off

apk add is already unversioned against the live index, so build reproducibility does not exist to lose. OpenSSF Scorecard's pinned-dependencies check has a closed enum of eight dependency types containing no package manager, so apk upgrade carries no penalty. Docker deleted the anti-upgrade guidance in 2021; hadolint removed DL3005 in 2023.

Verification

The nginx official image installs nginx from nginx.org via a one-shot apk add -X <url> repository that is not persisted, so apk upgrade draws from Alpine main/community only. Confirm nginx -v is unchanged and the container still serves after the change — a silent version swap would not be caught by the host smoke job.

Non-deferrable core

  • Both webapp/ and docker/agents/pi/ in the same PR — fixing one and leaving the other just moves the outage to the next release
  • The nginx -v / start-up verification recorded in the PR body

Metadata

Metadata

Assignees

No one assigned

    Labels

    ciGitHub Actions, workflows, build pipeline changespriority:criticalDrop everything - Loss of functionality or datasecurityAuthentication, authorization, vulnerability fixes

    Type

    No type

    Projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions