fix(docker): upgrade inherited base packages, and stop caching the layer that decides currency - #395
Conversation
|
Thanks for the detailed writeup, rubenhensen! I'm on it — reviewing the fix for both the inherited-package staleness and the GHA cache pinning it in place, plus checking the |
…yer that decides currency DSA-6465-1 (CVE-2026-63073, critical) shipped in both published images and blocked the 0.6.4 / 0.1.33 release. Two independent causes, and fixing either alone leaves the other. Inheritance. `debian:trixie-slim` ships `libssl3t64` and `openssl-provider-legacy` already installed — `openssl` and `ca-certificates` are not in the base — and `apt-get install` does not upgrade a package that is already present and satisfying. So `install ca-certificates libssl3` left both inherited packages at whatever the base snapshot froze, indefinitely. `apt-get upgrade -y` before the install moves them. No sources change is needed: the fix is in `trixie-security`, and the base image's own `rootfs.debian-sources` already lists that suite. Verified against the security archive's Packages index rather than inferred — all three of `openssl`, `openssl-provider-legacy` and `libssl3t64` are served there at 3.5.7-1~deb13u2. `upgrade`, not `dist-upgrade`: a release build should not be adding or removing packages to satisfy changed dependencies. Cache. Both image builds use `cache-from/to: type=gha,mode=max`, so the `RUN apt-get ...` layer is reused until the Dockerfile text changes. Package currency was therefore pinned to the last time someone edited a Dockerfile, and the scan reported the truth about a layer of unknown age — which is why a 2026-09-01 build shipped a package whose fix was already published. Both runtime stages are now named `runtime` and exempted with `no-cache-filters`, so apt re-runs every build while the cargo-chef stages, which are what the cache is for, stay cached. Note what this does not change: grype does no reachability analysis, and CVE-2026-63073 is an OpenSSL CMP client format-string bug that nothing in this workspace can reach — no CMP client here, OpenSSL is linked for TLS via native-tls. The gate blocked the release anyway, correctly per its current policy; #394 records the decision to keep `--fail-on critical` strict rather than add a suppression. `delivery.yml` runs on pull_request, so this PR's own scan jobs verify the fix against freshly built images. Closes #394.
e93758c to
6e7a802
Compare
Verified: both scans green at
|
There was a problem hiding this comment.
Checked the 3 changed files (delivery.yml, Dockerfile, cryptify/Dockerfile) against the code-comments rule (compliant, dense comments match this Dockerfile/workflow's existing WHY-comment density) and confirmed all 36 applicable CI checks pass; no blocking findings — the previous step's 5 findings reference files not present in this PR's diff (pg-core/src/client/mod.rs, pg-wasm/src/lib.rs, .DS_Store) and were excluded as inapplicable.
|
Reviewed and approved: #395 The repo's one binding rule (code-comments) checks out — the new Dockerfile/workflow comments explain the non-obvious why (upgrade-before-install ordering, cache exemption) at the same level of detail the rest of these files already use. One note: 5 findings handed to me from an earlier review step pointed at |
Closes #394. Unblocks #389 (
pg-pkg0.6.4,cryptify0.1.33).Two independent causes, and fixing either alone leaves the other
1. Inheritance.
debian:trixie-slimshipslibssl3t64andopenssl-provider-legacyalready installed at the base snapshot's version —opensslandca-certificatesare not in the base — andapt-get installdoes not upgrade a package that is already present and satisfying. Soinstall ca-certificates libssl3left both inherited packages frozen at whatever the snapshot carried, indefinitely.apt-get upgrade -ybefore the install moves them.No sources change is needed, which was the surprising part: the fix is in
trixie-security, and the base image's ownrootfs.debian-sourcesalready listsSuites: trixie-security. The archive was reachable the whole time; nothing ever asked it for anything.2. Cache. Both builds use
cache-from/to: type=gha,mode=max, so theRUN apt-get …layer is reused until the Dockerfile text changes. Package currency was pinned to the last time someone edited a Dockerfile, and the scan reported the truth about a layer of unknown age. That is how a build on 2026-09-01 shipped a package whose fix was already published. Both runtime stages are now namedruntimeand exempted viano-cache-filters; apt re-runs every build while the cargo-chef stages — what the cache is actually for — stay cached.Fixing only (1) would have worked once, on this commit, and then frozen again at the new layer. Fixing only (2) would rebuild the apt layer faithfully and still never upgrade the inherited packages.
Verification
3.5.7-1~deb13u2was read out of the security archive's ownPackagesindex rather than inferred from a fixed-version field:Worth recording that the first source consulted gave the wrong answer:
api.ftp-master.debian.org/madison?table=allshows3.5.7-1~deb13u2inproposed-updatesonly, which reads as "not reachable, wait for a point release". That table does not cover the security archive, which lives on a different host. The Debian security tracker namestrixie (security) 3.5.7-1~deb13u2 fixed, DSA-6465-1, and the archive index confirms it. A single authoritative-looking source said the fix was out of reach and it was one suite away.delivery.ymlruns onpull_request, so this PR's own scan jobs verify the fix against freshly built images — no merge-and-hope.cargo test --manifest-path pg-pkg/Cargo.toml --test dockerfile_workspace_memberspasses: the guard is per-stage and exempts stages that copy no workspace member, so naming the runtime stage does not touch it.What this deliberately does not change
Grype does no reachability analysis, and CVE-2026-63073 is unreachable from these binaries — it is a format-string bug in OpenSSL's CMP client (
ossl_cmp_msg_check_update()passing a peer-supplied sender DN toERR_raise_data()), reached only when validating a CMP response. Nothing in this workspace uses CMP; OpenSSL is linked for TLS vianative-tls. The gate blocked the release anyway, correctly under its current policy.#394 records the decision to keep
--fail-on criticalstrict rather than add a.grype.yamlsuppression — one unreachable CVE is not a pattern, an allowlist is the mechanism that quietly becomes permanent, and the strict gate just caught a real DSA that nothing else in the fleet would have.