Repository navigation
v0.41.1: the security patch layer only ran on a digest bump
The security patch layer only ran on a digest bump.
The Dockerfile has applied Debian's security patches at build time since July. The point was that a newly-disclosed base CVE with a released fix would clear on the next build, instead of waiting on a base-image digest bump. All three image builds pass cache-from: type=gha, and that RUN line never changes, so BuildKit replayed the layer. It did still run, but only ever incidentally: when the pinned digest moved and invalidated everything after it, or when the cache entry aged out. Its last two executions were 2026-08-31 and 2026-09-04. Never once because a fix was published. The control was pinned to exactly the cadence it was written to escape.
Read from the published images' own OCI configs: 0.41.0 was built 2026-09-13 and shipped the 2026-09-04 apt layer, byte-identical to 0.40.0's. That is why the two scan identically, at 3 CRITICAL and 9 HIGH Debian CVEs across perl-base, libpcre2-8-0, libsqlite3-0 and gzip. Debian 13.7 published every one of those fixes on 2026-09-12. The image went out one day behind the archive, and would have stayed behind: the pinned base is already the newest python:3.13-slim, so no digest bump was pending to carry them, and the digest bump was the only thing that ever did.
APT_SECURITY_EPOCH now carries the run id at every build site, so the layer rebuilds on each run. It is declared in the runtime stage because ARG scope is per-stage: from anywhere else it expands empty and caches forever. The added cost is the apt step alone. The hash-pinned pip install downstream already rebuilt every release, because the wheel changes each time, and the measured image job durations say rebuilding was never the slower path. tests/test_dockerfile_pins.py holds the ARG, its stage, and the build-arg at every call site, including a raw docker build and a .yaml workflow.
One seam opens on purpose. The scanning build and the release build now use different epochs, so the scanned apt layer is no longer the byte-identical one the release ships. The release layer is always the fresher of the two, so the drift runs safe, but the scan no longer speaks for the exact bytes.
If you run the container, pull it.
This release changes no tool, no API and no behaviour. What it changes is the packages inside the image. ghcr.io/john-broadway/proximo:0.41.1 is the rebuilt one. The PyPI and uvx paths were never affected, since these were base-OS packages in the container, not Proximo's dependencies.
The gate was working the whole time.
Trivy scans the image on every push to main and weekly, and it is what caught this. It went red when its vulnerability database learned the CVEs, not when the defect appeared, which is why a green scan last week said nothing about the image last week. A vulnerability scan is dated by its database, never by the code it points at.
Correction to the 0.41.0 notes.
They said the one contact that came through the removed HELLO door "arrived by email". Nothing supports that, and it should not have shipped. Nothing ever came through it.
Where to read more
- The two-deployment trust model, and the honest scope notes saying what does not hold: SECURITY.md
- Verifying the image signature, the SBOM and the provenance yourself: VERIFY.md
- Wiring it into an MCP client, least-privilege tokens, and the LXC one-liner: docs/SETUP.md
- Every tool, per plane: docs/TOOLS.md
- Full change detail: CHANGELOG.md
Install: uvx proximo-proxmox · pip install proximo-proxmox · ghcr.io/john-broadway/proximo:0.41.1