Skip to content

fix(docker): upgrade inherited base packages, and stop caching the layer that decides currency - #395

Merged
rubenhensen merged 1 commit into
mainfrom
fix/394-openssl-dsa-base-packages
Sep 1, 2026
Merged

fix(docker): upgrade inherited base packages, and stop caching the layer that decides currency#395
rubenhensen merged 1 commit into
mainfrom
fix/394-openssl-dsa-base-packages

Conversation

@rubenhensen

Copy link
Copy Markdown
Contributor

Closes #394. Unblocks #389 (pg-pkg 0.6.4, cryptify 0.1.33).

Two independent causes, and fixing either alone leaves the other

1. Inheritance. debian:trixie-slim ships libssl3t64 and openssl-provider-legacy already installed at the base snapshot's version — 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 frozen at whatever the snapshot carried, indefinitely. apt-get upgrade -y before 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 own rootfs.debian-sources already lists Suites: 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 the RUN 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 named runtime and exempted via no-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~deb13u2 was read out of the security archive's own Packages index rather than inferred from a fixed-version field:

libssl3t64: 3.5.7-1~deb13u2
openssl: 3.5.7-1~deb13u2
openssl-provider-legacy: 3.5.7-1~deb13u2

Worth recording that the first source consulted gave the wrong answer: api.ftp-master.debian.org/madison?table=all shows 3.5.7-1~deb13u2 in proposed-updates only, 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 names trixie (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.yml runs on pull_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_members passes: 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 to ERR_raise_data()), reached only when validating a CMP response. Nothing in this workspace uses CMP; OpenSSL is linked for TLS via native-tls. The gate blocked the release anyway, correctly under its current policy.

#394 records the decision to keep --fail-on critical strict rather than add a .grype.yaml suppression — 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.

@dobby-coder

dobby-coder Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

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 runtime-stage no-cache-filters exemption. I'll follow up shortly with a consolidated review on this PR.

…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.
@rubenhensen
rubenhensen force-pushed the fix/394-openssl-dsa-base-packages branch from e93758c to 6e7a802 Compare September 1, 2026 09:39
@rubenhensen

Copy link
Copy Markdown
Contributor Author

Verified: both scans green at 6e7a8027

Scan Docker image:    success
Scan cryptify image:  success

40 check-runs at the head sha, 36 success / 4 skipped, MERGEABLE. Read off the sha the PR points at now rather than from a watcher — the previous head (e93758c) was force-replaced during this PR's life, and a verdict about it would have been true of nothing.

This is the acceptance check from #394 stated as a command, and it ran on freshly built images: delivery.yml triggers on pull_request, and the runtime stages are now exempt from the layer cache, so the apt step genuinely re-executed rather than replaying the layer that carried the vulnerable packages.

Both halves were load-bearing. The cache exemption alone would have rebuilt apt faithfully and still shipped the inherited libssl3t64 and openssl-provider-legacy at their base-snapshot version, because apt-get install does not upgrade an already-satisfied package. The upgrade alone would have worked on this commit and then frozen again at the newly-cached layer. A green scan here does not distinguish them, which is why both are in the diff on argument rather than on evidence.

Note the build cost: the runtime stage now re-runs apt on every build. On a slim image that is seconds, and the cargo-chef stages — the reason the cache exists — are untouched.

@dobby-coder dobby-coder Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@dobby-coder

dobby-coder Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

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 pg-core/src/client/mod.rs, pg-wasm/src/lib.rs, and a root .DS_Store — none of which are touched by this PR (it only changes delivery.yml, Dockerfile, and cryptify/Dockerfile). They describe an unrelated, already-resolved doc-wording issue from #376, so I left them out rather than posting false findings here, and said so in the review body.

@rubenhensen
rubenhensen merged commit eaf7f71 into main Sep 1, 2026
40 checks passed
@github-actions github-actions Bot mentioned this pull request Sep 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

critical OpenSSL CVE in the Debian base blocks the release; the vulnerable path is unreachable from our binaries

1 participant