Repository navigation
Verify the DXVK and VKD3D-Proton downloads against pinned checksums - #17
Merged
Merged
Conversation
Both graphics translation layers were piped straight from a GitHub release into tar with no integrity check. The versions were ARG-pinned but the bytes were not, and a release tag is mutable: re-pushing a tag swaps what that URL serves, and nothing in the build would notice. What lands in /opt is a set of DLLs Wine loads into the process that drives the trainer, so this was the one unverified input left in an image whose apt packages and base images are already checked. Each archive now carries a sha256 next to its version ARG. The download writes to /tmp, both files are verified before either is extracted, and the tarballs are removed in the same layer. Neither upstream publishes a digest or signature, so the checksums are computed locally and corroborated only against the asset sizes GitHub's API reports; this is tamper evidence, not provenance. ADD --checksum was tested against podman 5.8.4 and does work, but ADD from a URL cannot extract, so both tarballs would be committed to a layer a later rm cannot reclaim: 228 MB against 205 MB on an identical base, 23 MB of dead weight in an image ADR-0008 had just trimmed by 60 MB. sha256sum is run with --strict deliberately. Without it a blank or malformed checksum line is only a warning and the build still exits 0, which would turn a half-finished version bump into a silently unverified extract. A full no-cache build of Containerfile.full succeeds in 7m12s and still produces a 6.63 GB image, with both archives extracted where build-prefix.sh expects them.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The problem
Containerfile.fullpiped both graphics translation layers from GitHub straight intotar:The versions were pinned; the bytes were not. A release tag is mutable — delete and re-push it and that URL serves something else, with nothing in the build to notice. What lands in
/optis DLLs Wine loads into the process driving the trainer. It was the only unverified download left: apt checks the Debian/WineHQ/Mesa packages against their keys, and the base images are digest-addressed.The pipe also made verification structurally impossible:
curl | tar -xextracts as it downloads, so the complete file never exists on disk to be inspected.What changed
Each checksum sits directly under the version it belongs to, so a bump that forgets the digest shows up in the diff:
One
RUNdownloads both, verifies both, then extracts both — so a bad DXVK tarball can't leave a half-populated/opt— and removes the archives in the same layer. No new packages:curlandzstdwere already kept by ADR-0008.Checksums are ours, computed by downloading the artefacts. Neither project publishes one — each release has exactly one asset, no
.sha256/.asc/.sig, and no digest in either release body. The only corroboration available is that both match the size GitHub's API reports for the asset. This is tamper evidence, not provenance, and the ADR says so.Why not
ADD --checksumIt was tested against the real podman 5.8.4 and does work — correct sum builds, wrong sum fails with
unexpected response digest. Rejected anyway:ADDfrom a URL does not extract, so a laterRUNmust unpack, and thatRUN'srmcannot reclaim whatADDalready committed. Measured on an identical base:debian:trixie+ curl, zstd)ADD --checksum×2 +RUN tar && rmRUNcurl + verify + tar + rm23 MB of permanently stranded tarball — a third of what ADR-0008 had just clawed back.
Evidence the gate bites
Happy path — a full
podman build --no-cache -f Containerfile.full, not just the layer: succeeds in 7m12s, image 6.63 GB (unchanged from ADR-0008, so thermdoes reclaim), both archives extracted wherebuild-prefix.sh's/opt/dxvk-*//opt/vkd3d-proton-*globs find them, and the prefix resolvessystem32/d3d12.dll -> /opt/vkd3d-proton-3.0.1/x64/d3d12.dll.Corrupted checksum —
DXVK_SHA256set todeadbe…:--strictturned out to be load-bearing. The first draft used a plainsha256sum -c -, which is quietly broken: a blank or malformed checksum line is only a warning and the build still exits 0. BlankingDXVK_SHA256proves it:Without
--strictthe gate degrades silently to no gate in exactly the case it most needs to hold — a half-finished version bump.What it costs
--strictaway reopens the hole.entrypoint.shfetches it at runtime from a vendor URL, and it self-updates, so a pinned digest would break it rather than protect it. The image's largest unverified input stays unverified; that needs its own change.Linters run locally: shellcheck
--severity=warning, ruff 0.11.7 ontools/, hadolint v2.15.1-alpine on both Containerfiles with the repo's ignore set — all clean.ADR:
docs/adr/0009-verify-the-dxvk-and-vkd3d-downloads-against-pinned-checksums.md(Builds on ADR-0008).