From bc1d6890b64d9b8a2602dfffe516a708e633eed7 Mon Sep 17 00:00:00 2001 From: agent Date: Mon, 31 Aug 2026 12:56:44 +0200 Subject: [PATCH] fix: bake openssl and jq into the runner image, and assert them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release tag gate parses the Control Plane quorum verdict and verifies its Ed25519 DSSE signature by shelling out to jq and openssl. Neither is in this image, and both call sites read cmd ... || { echo ; exit 1; }, so command-not-found took the failure branch: the gate reported a valid, signed approval first as "not a signed DSSE envelope" and then as "signature FAILED verification". That blocked v0.0.134 and v0.0.135 on 2026-08-31 and pointed the investigation at the Tag Request rather than at this image — the same shape as the git-daemon gap already documented above the package list. Also adds both to the toolchain assertion. That check already existed and still missed them, because it only covers what someone thought to list; the comment now says so, and says to extend it whenever a gate grows a shell dependency. Verified by building this image and running the gate script inside it against the live Control Plane: openssl 3.5.8, jq 1.8.1, and the v0.0.135 verdict verifies and binds to its commit. The unpatched image fails the same script. --- .github/workflows/build-image.yml | 10 ++++++++++ Dockerfile | 17 ++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-image.yml b/.github/workflows/build-image.yml index 7359e17..fd3474f 100644 --- a/.github/workflows/build-image.yml +++ b/.github/workflows/build-image.yml @@ -101,6 +101,14 @@ jobs: # # Asserted on BOTH architectures, because a package that resolves on amd64 # and not on arm64 would otherwise reach half the nodes unnoticed. + # + # openssl and jq were added after this check already existed and still + # missed them: the release tag gate shells out to both to verify the + # Control Plane's signed quorum verdict, and their absence surfaced as + # "verdict not signed" / "signature FAILED verification" rather than as a + # missing tool, blocking v0.0.134 and v0.0.135. The list only covers what + # someone remembered to add, so add to it whenever a gate grows a new + # shell dependency. - name: Verify the image still contains the toolchain the gates need if: ${{ steps.meta.outputs.push == 'true' }} run: | @@ -119,6 +127,8 @@ jobs: command -v make >/dev/null && echo "make=ok" || echo "make=MISSING" command -v curl >/dev/null && echo "curl=ok" || echo "curl=MISSING" command -v tar >/dev/null && echo "tar=ok" || echo "tar=MISSING" + command -v openssl >/dev/null && echo "openssl=ok" || echo "openssl=MISSING" + command -v jq >/dev/null && echo "jq=ok" || echo "jq=MISSING" [ -x "$(git --exec-path)/git-http-backend" ] \ && echo "git-http-backend=ok" || echo "git-http-backend=MISSING" ' 2>&1) || { echo "::error::could not run $REF on $plat"; fail=1; continue; } diff --git a/Dockerfile b/Dockerfile index 97a4a60..2806d9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -38,6 +38,19 @@ USER root # curl,tar -> setup-go / gitleaks download + extract their own arch-specific binaries # make -> zegit Makefile targets # ca-certificates -> trusted roots for HTTPS to gitea/github/goproxy +# openssl -> the release tag gate verifies the Control Plane's SIGNED quorum +# verdict (Ed25519 DSSE) with `openssl pkeyutl -verify -rawin`. +# Absent, that command failed "command not found" and the gate's +# `|| { echo ...; exit 1; }` reported it as "Quorum verdict +# signature FAILED verification" -- a TOOLING gap narrated as a +# SECURITY verdict, pointing the investigation at a perfectly +# valid signed approval instead of at this image. It blocked +# v0.0.134 and v0.0.135 on 2026-08-31. +# jq -> the same story one step earlier: the gate parsed that envelope +# with `jq -e`, and a missing jq was reported as "not a signed +# DSSE envelope". jq is the reflex tool for JSON in shell steps, +# so its absence keeps resurfacing as a misleading failure in +# whichever step reaches for it next. # gcc,musl-dev -> C toolchain for cgo; `go test -race` (the Makefile test # target) requires cgo, which needs a C compiler + libc headers # (musl on Alpine) @@ -60,7 +73,9 @@ RUN apk add --no-cache \ gcc \ musl-dev \ python3 \ - py3-yaml + py3-yaml \ + openssl \ + jq # Match the runner pod's runAsUser (1000); keep the image non-root by default. USER 1000 -- 2.54.0