From 3b49f4d3f76fff100bf73f519b4859bc966a3a4f Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:00:19 +0800 Subject: [PATCH 1/8] build: refresh October security pins and trust stores --- .github/workflows/security-build.yml | 39 ++++++++++++++++++++++++++++ Dockerfile | 20 +++++++++++--- Makefile | 2 +- ORIGIN.md | 2 +- README.md | 8 ++++-- scripts/integration-smoke | 2 +- 6 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 .github/workflows/security-build.yml diff --git a/.github/workflows/security-build.yml b/.github/workflows/security-build.yml new file mode 100644 index 0000000..f0592c9 --- /dev/null +++ b/.github/workflows/security-build.yml @@ -0,0 +1,39 @@ +name: Security build verification + +on: + pull_request: + workflow_dispatch: + +permissions: + contents: read + +jobs: + verify: + runs-on: ubuntu-24.04 + timeout-minutes: 60 + env: + GOTOOLCHAIN: local + GOMAXPROCS: 2 + GOFLAGS: -p=2 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + - name: Install checksum-pinned Go compiler + shell: bash + run: | + set -euo pipefail + curl --proto '=https' --tlsv1.2 --fail --silent --show-error --location \ + --output "$RUNNER_TEMP/go.tar.gz" https://go.dev/dl/go1.27.3.linux-amd64.tar.gz + printf '%s %s\n' 65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40 "$RUNNER_TEMP/go.tar.gz" | sha256sum -c - + tar -C "$RUNNER_TEMP" -xzf "$RUNNER_TEMP/go.tar.gz" + echo "$RUNNER_TEMP/go/bin" >> "$GITHUB_PATH" + - name: Validate source and build the updated runtime + shell: bash + run: | + set -euo pipefail + test "$(go env GOVERSION)" = go1.27.3 + make validate test + make build smoke integration + diff --git a/Dockerfile b/Dockerfile index 42a6e9e..965d395 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,8 +4,8 @@ ARG UBUNTU_IMAGE=ubuntu:26.04@sha256:2260313b31c8c011cd2eebe728008efac1b3982be73eb71348ea2648d2c0e09b FROM ${UBUNTU_IMAGE} AS tool-builder -ARG GO_VERSION=1.27.0 -ARG GO_SHA256_amd64=675c26c449cbb18fc24b74650de1eabbae6e16f64326fd85a283fb3b58280685 +ARG GO_VERSION=1.27.3 +ARG GO_SHA256_amd64=65efbc80fdc1fa2cd2631cad5b481777a68e8725f34e89f50fc6ac714e379b40 ARG YQ_VERSION=v4.53.3 ARG YQ_GIT_COMMIT=1b9b4ac5187171d2e5e3129be0cfa827c7f9d53d ARG GOMPLATE_VERSION=v5.1.0 @@ -15,8 +15,8 @@ ARG DOCKER_GIT_COMMIT=055a478ea9010a19d0d4674c0d0e87ade37a4223 ARG DOCKER_SOURCE_DATE_EPOCH=1776697064 ARG UBUNTU_SNAPSHOT=20260825T000000Z -ADD --checksum=sha256:6077d27c6b6f8b23590cb01ff877ed8c804a67a5442cc32b5a33da10d2bd0e90 \ - https://snapshot.ubuntu.com/ubuntu/20260825T000000Z/pool/main/c/ca-certificates/ca-certificates_20260601~26.04.1_all.deb \ +ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd \ + https://archive.ubuntu.com/ubuntu/pool/main/c/ca-certificates/ca-certificates_20260816ubuntu0.26.04.1_all.deb \ /tmp/ca-certificates.deb ENV DEBIAN_FRONTEND=noninteractive \ @@ -28,6 +28,7 @@ ENV DEBIAN_FRONTEND=noninteractive \ GOTELEMETRY=off \ PATH=/usr/local/go/bin:${PATH} +ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd https://archive.ubuntu.com/ubuntu/pool/main/c/ca-certificates/ca-certificates_20260816ubuntu0.26.04.1_all.deb /opt/pasturestack-ca-certificates.deb RUN set -eux; \ mkdir -p /tmp/ca-bootstrap /etc/ssl/certs; \ dpkg-deb --extract /tmp/ca-certificates.deb /tmp/ca-bootstrap; \ @@ -45,6 +46,11 @@ RUN set -eux; \ libc6-dev \ make \ tar; \ + dpkg -i /opt/pasturestack-ca-certificates.deb && \ + update-ca-certificates --fresh && \ + test "$(dpkg-query -W -f='${Version}' ca-certificates)" = '20260816ubuntu0.26.04.1' && \ + test ! -e /usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt && \ + rm -f /opt/pasturestack-ca-certificates.deb && \ rm -rf /var/lib/apt/lists/* RUN set -eux; \ @@ -114,6 +120,7 @@ COPY --from=tool-builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-ce ENV DEBIAN_FRONTEND=noninteractive \ SYSTEM_IMAGE_PRELOADER_VERSION=${IMAGE_VERSION} +ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd https://archive.ubuntu.com/ubuntu/pool/main/c/ca-certificates/ca-certificates_20260816ubuntu0.26.04.1_all.deb /opt/pasturestack-ca-certificates.deb RUN set -eux; \ rm -f /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources; \ printf 'Types: deb\nURIs: https://snapshot.ubuntu.com/ubuntu/%s\nSuites: resolute resolute-updates resolute-backports resolute-security\nComponents: main universe restricted multiverse\nSigned-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\nSnapshot: no\n' "${UBUNTU_SNAPSHOT}" > /etc/apt/sources.list.d/pasturestack-snapshot.sources; \ @@ -130,6 +137,11 @@ RUN set -eux; \ procps \ sed; \ rm -f /usr/bin/pebble; \ + dpkg -i /opt/pasturestack-ca-certificates.deb && \ + update-ca-certificates --fresh && \ + test "$(dpkg-query -W -f='${Version}' ca-certificates)" = '20260816ubuntu0.26.04.1' && \ + test ! -e /usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt && \ + rm -f /opt/pasturestack-ca-certificates.deb && \ rm -rf /var/lib/apt/lists/* COPY --from=tool-builder /out/yq /usr/local/bin/yq diff --git a/Makefile b/Makefile index b3fcc06..a24858c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Created by PastureStack contributors for repeatable validation. -VERSION ?= v0.3.0 +VERSION ?= v0.3.1 REVISION ?= $(shell git rev-parse HEAD) IMAGE_REPOSITORY ?= local/system-image-preloader IMAGE ?= $(IMAGE_REPOSITORY):$(VERSION) diff --git a/ORIGIN.md b/ORIGIN.md index b257e9e..e1c8e73 100644 --- a/ORIGIN.md +++ b/ORIGIN.md @@ -23,7 +23,7 @@ The container build includes separately maintained tools: - `yq` `v4.53.3`, built from its verified upstream commit; and - `gomplate` `v5.1.0`, built from its verified upstream commit. -The source-built Go tools use Go `1.27.0`. The `gomplate` build updates +The source-built Go tools use Go `1.27.3`. The `gomplate` build updates dependencies with published security fixes while retaining the verified `v5.1.0` application source. diff --git a/README.md b/README.md index 4833de8..5a92235 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ This repository is a derivative maintenance project. It preserves the upstream G ## Reviewed release -The `v0.3.0` release provides: +The `v0.3.1` release provides: - a self-contained public build based on a digest-pinned Ubuntu image; - the `system-image-preloader` executable and image name; @@ -72,7 +72,7 @@ restores the image-presence state. It never performs a broad image prune. Use the immutable semantic tag: ```text -ghcr.io/pasturestack/system-image-preloader:v0.3.0 +ghcr.io/pasturestack/system-image-preloader:v0.3.1 ``` The deployment definition must mount `/var/run/docker.sock`, run one instance @@ -115,3 +115,7 @@ The repository remains under its existing Apache License 2.0 file. The runtime i ## Localization This project is a background service with no user interface or runtime localization subsystem. It therefore does not add locale files. User-facing dashboards that manage this service must provide Traditional Chinese through their own locale framework. + +## October 2026 security maintenance + +Maintained Go builds select the patched Go 1.27.3 compiler without raising the existing Go language requirement. Ubuntu build/runtime stages apply the checksum-pinned `ca-certificates 20260816ubuntu0.26.04.1` security package after their frozen APT baseline; the final trust store and installed version are verified. Release artifacts must pass the repository's existing checks before publication. diff --git a/scripts/integration-smoke b/scripts/integration-smoke index 927a636..f1c1390 100755 --- a/scripts/integration-smoke +++ b/scripts/integration-smoke @@ -4,7 +4,7 @@ set -Eeuo pipefail PROJECT_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -IMAGE="${IMAGE:-local/system-image-preloader:v0.3.0}" +IMAGE="${IMAGE:-local/system-image-preloader:v0.3.1}" TEST_PULL_IMAGE="${TEST_PULL_IMAGE:-ghcr.io/pasturestack/container-cron:v0.6.0}" PLATFORM_VERSION="${PLATFORM_VERSION:-v1.6.281}" ACCESS_KEY="integration-access" From 55b0f3cad7507edb6fab2bbca4f54d2810844027 Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:09:44 +0800 Subject: [PATCH 2/8] ci: retain exact versioned runtime artifacts --- .github/workflows/security-build.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/security-build.yml b/.github/workflows/security-build.yml index f0592c9..7655936 100644 --- a/.github/workflows/security-build.yml +++ b/.github/workflows/security-build.yml @@ -36,4 +36,20 @@ jobs: test "$(go env GOVERSION)" = go1.27.3 make validate test make build smoke integration + - name: Retain the exact verified runtime + shell: bash + run: | + set -euo pipefail + mkdir -p dist/security-runtime + docker image inspect local/system-image-preloader:v0.3.1 > dist/security-runtime/images.json + docker save local/system-image-preloader:v0.3.1 | gzip -n > dist/security-runtime/images.tar.gz + printf '%s\n' "$GITHUB_SHA" > dist/security-runtime/source-revision.txt + (cd dist/security-runtime && sha256sum images.json images.tar.gz source-revision.txt > SHA256SUMS) + - name: Upload verified runtime and checksums + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: security-runtime-${{ github.sha }} + path: dist/security-runtime/ + if-no-files-found: error + retention-days: 14 From 680760cbe1a8c9d004ecf802a76fbaaabb52522c Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:13:22 +0800 Subject: [PATCH 3/8] build: align security gates and artifact inputs --- .github/workflows/security-build.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/security-build.yml b/.github/workflows/security-build.yml index 7655936..829bdd9 100644 --- a/.github/workflows/security-build.yml +++ b/.github/workflows/security-build.yml @@ -52,4 +52,3 @@ jobs: path: dist/security-runtime/ if-no-files-found: error retention-days: 14 - From 79b28a1bf80fee21727eda895e1101daf2ebf83e Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:18:07 +0800 Subject: [PATCH 4/8] fix: patch source-built tool HTTP/2 dependencies --- Dockerfile | 2 +- README.md | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 965d395..8b0cdf2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -80,7 +80,7 @@ RUN set -eux; \ github.com/go-git/go-billy/v5@v5.9.0 \ github.com/go-git/go-git/v5@v5.19.0 \ golang.org/x/crypto@v0.52.0 \ - golang.org/x/net@v0.55.0 \ + golang.org/x/net@v0.60.0 \ google.golang.org/grpc@v1.82.1; \ go mod tidy; \ go build -trimpath -buildvcs=false \ diff --git a/README.md b/README.md index 5a92235..e8c9971 100644 --- a/README.md +++ b/README.md @@ -118,4 +118,6 @@ This project is a background service with no user interface or runtime localizat ## October 2026 security maintenance +The source-built gomplate helper selects `golang.org/x/net v0.60.0` for the October HTTP/2 fixes. + Maintained Go builds select the patched Go 1.27.3 compiler without raising the existing Go language requirement. Ubuntu build/runtime stages apply the checksum-pinned `ca-certificates 20260816ubuntu0.26.04.1` security package after their frozen APT baseline; the final trust store and installed version are verified. Release artifacts must pass the repository's existing checks before publication. From 03db161c75191229f5f794a30a505dd2860f1454 Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:19:01 +0800 Subject: [PATCH 5/8] fix: align x/net transitive module requirements --- Dockerfile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 8b0cdf2..e874d5f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -79,15 +79,17 @@ RUN set -eux; \ go get \ github.com/go-git/go-billy/v5@v5.9.0 \ github.com/go-git/go-git/v5@v5.19.0 \ - golang.org/x/crypto@v0.52.0 \ + golang.org/x/crypto@v0.57.0 \ golang.org/x/net@v0.60.0 \ google.golang.org/grpc@v1.82.1; \ go mod tidy; \ + test "$(go list -m -f '{{.Version}}' golang.org/x/net)" = v0.60.0; \ go build -trimpath -buildvcs=false \ -ldflags "-s -w -X github.com/hairyhenderson/gomplate/v5/version.Version=${GOMPLATE_VERSION} -X github.com/hairyhenderson/gomplate/v5/version.GitCommit=${GOMPLATE_GIT_COMMIT}" \ -o /out/gomplate ./cmd/gomplate; \ cp LICENSE /out/licenses/gomplate/LICENSE; \ /out/gomplate --version; \ + go version -m /out/gomplate | grep -F 'golang.org/x/net'; \ rm -rf /src/gomplate /tmp/go-build-cache /tmp/go-mod-cache RUN set -eux; \ @@ -97,6 +99,11 @@ RUN set -eux; \ https://github.com/docker/cli /go/src/github.com/docker/cli; \ cd /go/src/github.com/docker/cli; \ test "$(git rev-parse HEAD)" = "${DOCKER_GIT_COMMIT}"; \ + cp vendor.mod go.mod; \ + cp vendor.sum go.sum; \ + go get golang.org/x/net@v0.60.0; \ + go mod vendor; \ + test "$(go list -m -f '{{.Version}}' golang.org/x/net)" = v0.60.0; \ CGO_ENABLED=0 \ GOPATH=/go \ GO_STRIP=1 \ From 35fbb08a2b7ca5c78207e33a1d0d9e2a57af240c Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:36:32 +0800 Subject: [PATCH 6/8] security: scan patched runtimes and publish exact verified artifacts --- .github/workflows/security-build.yml | 60 +++++++++++++++++++++++++ Dockerfile | 6 +++ scripts/install-ubuntu-security-updates | 51 +++++++++++++++++++++ ubuntu-security-packages.lock | 32 +++++++++++++ 4 files changed, 149 insertions(+) create mode 100644 scripts/install-ubuntu-security-updates create mode 100644 ubuntu-security-packages.lock diff --git a/.github/workflows/security-build.yml b/.github/workflows/security-build.yml index 829bdd9..6f198e9 100644 --- a/.github/workflows/security-build.yml +++ b/.github/workflows/security-build.yml @@ -45,10 +45,70 @@ jobs: docker save local/system-image-preloader:v0.3.1 | gzip -n > dist/security-runtime/images.tar.gz printf '%s\n' "$GITHUB_SHA" > dist/security-runtime/source-revision.txt (cd dist/security-runtime && sha256sum images.json images.tar.gz source-revision.txt > SHA256SUMS) + - name: Scan the exact runtime and generate its SBOM + shell: bash + run: | + set -euo pipefail + scanner=aquasec/trivy:0.74.0@sha256:62b1e65e8869bc4b4c6aa4fa2b21595256c7c2f6018a9d9ad61caf87187c1969 + docker pull "$scanner" + for runtime in local/system-image-preloader:v0.3.1; do + name=${runtime##*/}; name=${name%%:*} + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v "$PWD/dist/security-runtime:/evidence" "$scanner" image --scanners vuln,secret --severity HIGH,CRITICAL --exit-code 1 --format json --output "/evidence/$name-security.json" "$runtime" + docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v "$PWD/dist/security-runtime:/evidence" "$scanner" image --format cyclonedx --output "/evidence/$name-sbom.cdx.json" "$runtime" + done + (cd dist/security-runtime && sha256sum -- *.json images.tar.gz source-revision.txt > SHA256SUMS) - name: Upload verified runtime and checksums + if: always() uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: security-runtime-${{ github.sha }} path: dist/security-runtime/ if-no-files-found: error retention-days: 14 + + publish: + if: github.event_name == 'workflow_dispatch' && github.ref == 'refs/heads/main' + needs: verify + runs-on: ubuntu-24.04 + timeout-minutes: 30 + permissions: + contents: write + actions: read + packages: write + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: v0.3.1 + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 0 + persist-credentials: false + - name: Publish only this run's verified immutable runtime + shell: bash + run: | + set -euo pipefail + test "$(git rev-parse HEAD)" = "$GITHUB_SHA" + test "$(git rev-parse "refs/tags/$RELEASE_TAG^{}")" = "$GITHUB_SHA" + gh run download "$GITHUB_RUN_ID" --repo "$GITHUB_REPOSITORY" --name "security-runtime-$GITHUB_SHA" --dir dist/security-runtime + test "$(cat dist/security-runtime/source-revision.txt)" = "$GITHUB_SHA" + (cd dist/security-runtime && sha256sum --check SHA256SUMS) + gzip -dc dist/security-runtime/images.tar.gz | docker load + printf '%s' "$GH_TOKEN" | docker login ghcr.io -u "$GITHUB_ACTOR" --password-stdin + trap 'docker logout ghcr.io >/dev/null 2>&1 || true' EXIT + : > dist/security-runtime/registry-images.jsonl + local_image='local/system-image-preloader:v0.3.1' + remote_image="ghcr.io/pasturestack/system-image-preloader:$RELEASE_TAG" + if docker manifest inspect "$remote_image" >/dev/null 2>"$RUNNER_TEMP/manifest-error"; then + echo "Refusing to replace an existing immutable image tag: $remote_image" >&2; exit 1 + else + grep -Eq 'manifest unknown|no such manifest' "$RUNNER_TEMP/manifest-error" + fi + docker tag "$local_image" "$remote_image" + docker push "$remote_image" | tee "$RUNNER_TEMP/push-log" + pushed=$(awk '/digest: sha256:/{for(i=1;i<=NF;i++) if($i=="digest:") print $(i+1)}' "$RUNNER_TEMP/push-log") + readback=$(docker buildx imagetools inspect "$remote_image" | awk '$1=="Digest:"{print $2; exit}') + test "$pushed" = "$readback" + [[ "$readback" =~ ^sha256:[0-9a-f]{64}$ ]] + jq -n --arg image "$remote_image" --arg digest "$readback" --arg source "$GITHUB_SHA" '{image:$image,digest:$digest,source:$source}' >> dist/security-runtime/registry-images.jsonl + sha256sum dist/security-runtime/registry-images.jsonl > dist/security-runtime/registry-images.sha256 + gh release create "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" --verify-tag --title "$GITHUB_REPOSITORY $RELEASE_TAG" --notes "Official security rebuild from $GITHUB_SHA. The release contains the exact tested/scanned runtime archive, SBOMs, and registry digest readbacks. No deployment is included." dist/security-runtime/* diff --git a/Dockerfile b/Dockerfile index e874d5f..a2ca11b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -28,6 +28,8 @@ ENV DEBIAN_FRONTEND=noninteractive \ GOTELEMETRY=off \ PATH=/usr/local/go/bin:${PATH} +COPY ubuntu-security-packages.lock /licenses/ubuntu-security-packages.lock +COPY scripts/install-ubuntu-security-updates /usr/local/libexec/pasturestack/install-ubuntu-security-updates ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd https://archive.ubuntu.com/ubuntu/pool/main/c/ca-certificates/ca-certificates_20260816ubuntu0.26.04.1_all.deb /opt/pasturestack-ca-certificates.deb RUN set -eux; \ mkdir -p /tmp/ca-bootstrap /etc/ssl/certs; \ @@ -51,6 +53,7 @@ RUN set -eux; \ test "$(dpkg-query -W -f='${Version}' ca-certificates)" = '20260816ubuntu0.26.04.1' && \ test ! -e /usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt && \ rm -f /opt/pasturestack-ca-certificates.deb && \ + sh /usr/local/libexec/pasturestack/install-ubuntu-security-updates /licenses/ubuntu-security-packages.lock /etc/ssl/certs/ca-certificates.crt && \ rm -rf /var/lib/apt/lists/* RUN set -eux; \ @@ -127,6 +130,8 @@ COPY --from=tool-builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-ce ENV DEBIAN_FRONTEND=noninteractive \ SYSTEM_IMAGE_PRELOADER_VERSION=${IMAGE_VERSION} +COPY ubuntu-security-packages.lock /licenses/ubuntu-security-packages.lock +COPY scripts/install-ubuntu-security-updates /usr/local/libexec/pasturestack/install-ubuntu-security-updates ADD --checksum=sha256:5b6326f1932cfd7be57130561dc78192f09ed9f58bfbe6606ed0c50510c3b6cd https://archive.ubuntu.com/ubuntu/pool/main/c/ca-certificates/ca-certificates_20260816ubuntu0.26.04.1_all.deb /opt/pasturestack-ca-certificates.deb RUN set -eux; \ rm -f /etc/apt/sources.list /etc/apt/sources.list.d/*.list /etc/apt/sources.list.d/*.sources; \ @@ -149,6 +154,7 @@ RUN set -eux; \ test "$(dpkg-query -W -f='${Version}' ca-certificates)" = '20260816ubuntu0.26.04.1' && \ test ! -e /usr/share/ca-certificates/mozilla/emSign_ECC_Root_CA_-_G3.crt && \ rm -f /opt/pasturestack-ca-certificates.deb && \ + sh /usr/local/libexec/pasturestack/install-ubuntu-security-updates /licenses/ubuntu-security-packages.lock /etc/ssl/certs/ca-certificates.crt && \ rm -rf /var/lib/apt/lists/* COPY --from=tool-builder /out/yq /usr/local/bin/yq diff --git a/scripts/install-ubuntu-security-updates b/scripts/install-ubuntu-security-updates new file mode 100644 index 0000000..054c893 --- /dev/null +++ b/scripts/install-ubuntu-security-updates @@ -0,0 +1,51 @@ +#!/bin/sh +# Same-series official micro-updates. Never install a package just for a scan. +set -eu +test "$#" -eq 2 || { echo 'usage: security-updates LOCK TRUSTED_CA_BUNDLE' >&2; exit 2; } +lock=$1 +trusted_ca=$2 +. /etc/os-release +test "$ID:$VERSION_ID" = ubuntu:26.04 +test -s "$lock" +test -s "$trusted_ca" +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT HUP INT TERM +dpkg-query -W -f='${binary:Package}\t${db:Status-Status}\n' | LC_ALL=C sort > "$tmp/before" +set -- +while IFS= read -r entry || test -n "$entry"; do + case "$entry" in ''|'#'*) continue;; esac + case "$entry" in *[!a-zA-Z0-9.:+~=_-]*) echo "Invalid lock entry" >&2; exit 1;; esac + package=${entry%%=*} + version=${entry#*=} + test "$package" != "$version" + status=$(dpkg-query -W -f='${db:Status-Status}' "$package" 2>/dev/null || true) + test "$status" = installed || continue + installed=$(dpkg-query -W -f='${Version}' "$package") + # A newer base may already contain the fix; never downgrade it. + dpkg --compare-versions "$installed" ge "$version" && continue + set -- "$@" "$entry" +done < "$lock" +if test "$#" -gt 0; then + printf 'Types: deb\nURIs: https://snapshot.ubuntu.com/ubuntu/20261023T000000Z\nSuites: resolute-updates resolute-security\nComponents: main\nSigned-By: /usr/share/keyrings/ubuntu-archive-keyring.gpg\nSnapshot: no\n' > "$tmp/security.sources" + apt_security() { + apt-get -o Dir::Etc::sourcelist="$tmp/security.sources" \ + -o Dir::Etc::sourceparts=- -o Acquire::https::CaInfo="$trusted_ca" \ + -o Acquire::https::Verify-Peer=true -o Acquire::https::Verify-Host=true \ + -o Acquire::AllowInsecureRepositories=false -o APT::Get::AllowUnauthenticated=false \ + -o Acquire::Retries=5 "$@" + } + apt_security update + DEBIAN_FRONTEND=noninteractive apt_security install -y --only-upgrade --no-install-recommends --no-remove "$@" +fi +while IFS= read -r entry || test -n "$entry"; do + case "$entry" in ''|'#'*) continue;; esac + package=${entry%%=*} + version=${entry#*=} + status=$(dpkg-query -W -f='${db:Status-Status}' "$package" 2>/dev/null || true) + test "$status" = installed || continue + dpkg --compare-versions "$(dpkg-query -W -f='${Version}' "$package")" ge "$version" +done < "$lock" +dpkg-query -W -f='${binary:Package}\t${db:Status-Status}\n' | LC_ALL=C sort > "$tmp/after" +# A security micro-update must not add/remove packages or change installed status. +cmp "$tmp/before" "$tmp/after" +printf 'UBUNTU_SECURITY_MICRO_UPDATES_OK\n' diff --git a/ubuntu-security-packages.lock b/ubuntu-security-packages.lock new file mode 100644 index 0000000..5cf2cd6 --- /dev/null +++ b/ubuntu-security-packages.lock @@ -0,0 +1,32 @@ +# Official Ubuntu 26.04 security/updates snapshot: 20261023T000000Z +# Existing packages only; ABI series and unrelated packages are preserved. +bsdutils=1:2.41.3-3ubuntu2.2 +curl=8.18.0-1ubuntu2.8 +diffutils=1:3.12-1ubuntu0.1 +gnu-coreutils=9.7-3ubuntu2.1 +gpgv=2.4.8-4ubuntu3.1 +libattr1=1:2.5.2-4ubuntu0.1 +libblkid1=2.41.3-3ubuntu2.2 +libbz2-1.0=1.0.8-6ubuntu0.1 +libc-bin=2.43-2ubuntu2.4 +libc-gconv-modules-extra=2.43-2ubuntu2.4 +libc6=2.43-2ubuntu2.4 +libc6-dev=2.43-2ubuntu2.4 +libcurl4t64=8.18.0-1ubuntu2.8 +libgcrypt20=1.12.0-2ubuntu1.1 +libmount1=2.41.3-3ubuntu2.2 +libperl5.40=5.40.1-7ubuntu0.3 +libsmartcols1=2.41.3-3ubuntu2.2 +libssh2-1t64=1.11.1-1ubuntu0.26.04.4 +libssl3t64=3.5.5-1ubuntu3.7 +libuuid1=2.41.3-3ubuntu2.2 +linux-libc-dev=7.0.0-38.38 +login=1:4.16.0-2+really2.41.3-3ubuntu2.2 +mount=2.41.3-3ubuntu2.2 +openssl=3.5.5-1ubuntu3.7 +openssl-provider-legacy=3.5.5-1ubuntu3.7 +perl=5.40.1-7ubuntu0.3 +perl-base=5.40.1-7ubuntu0.3 +perl-modules-5.40=5.40.1-7ubuntu0.3 +util-linux=2.41.3-3ubuntu2.2 +zlib1g=1:1.3.dfsg+really1.3.1-1ubuntu3.2 From 87cb9b253fbb880621aa593d60771a103bdb6720 Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:38:39 +0800 Subject: [PATCH 7/8] ci: scan saved runtime bytes without sharing the Docker socket --- .github/workflows/security-build.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/security-build.yml b/.github/workflows/security-build.yml index 6f198e9..dd63984 100644 --- a/.github/workflows/security-build.yml +++ b/.github/workflows/security-build.yml @@ -53,8 +53,9 @@ jobs: docker pull "$scanner" for runtime in local/system-image-preloader:v0.3.1; do name=${runtime##*/}; name=${name%%:*} - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v "$PWD/dist/security-runtime:/evidence" "$scanner" image --scanners vuln,secret --severity HIGH,CRITICAL --exit-code 1 --format json --output "/evidence/$name-security.json" "$runtime" - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v "$PWD/dist/security-runtime:/evidence" "$scanner" image --format cyclonedx --output "/evidence/$name-sbom.cdx.json" "$runtime" + docker save "$runtime" --output "$RUNNER_TEMP/$name.tar" + docker run --rm -v "$RUNNER_TEMP/$name.tar:/image.tar:ro" -v "$PWD/dist/security-runtime:/evidence" "$scanner" image --input /image.tar --scanners vuln,secret --severity HIGH,CRITICAL --exit-code 1 --format json --output "/evidence/$name-security.json" + docker run --rm -v "$RUNNER_TEMP/$name.tar:/image.tar:ro" -v "$PWD/dist/security-runtime:/evidence" "$scanner" image --input /image.tar --format cyclonedx --output "/evidence/$name-sbom.cdx.json" done (cd dist/security-runtime && sha256sum -- *.json images.tar.gz source-revision.txt > SHA256SUMS) - name: Upload verified runtime and checksums From abf8b5bfa5596533c9551e147d7dd25c0750076c Mon Sep 17 00:00:00 2001 From: chen21019 <19357113+chen21019@users.noreply.github.com> Date: Fri, 23 Oct 2026 20:53:44 +0800 Subject: [PATCH 8/8] Patch actual bundled helper module graphs --- Dockerfile | 11 ++++++++--- README.md | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index a2ca11b..9eea8af 100644 --- a/Dockerfile +++ b/Dockerfile @@ -69,6 +69,8 @@ RUN set -eux; \ git clone --branch "${YQ_VERSION}" --depth 1 https://github.com/mikefarah/yq /src/yq; \ cd /src/yq; \ test "$(git rev-parse HEAD)" = "${YQ_GIT_COMMIT}"; \ + go get golang.org/x/net@v0.60.0 golang.org/x/text@v0.42.0; \ + go mod tidy; \ go build -trimpath -buildvcs=false -ldflags "-s -w -X github.com/mikefarah/yq/v4/cmd.GitCommit=${YQ_GIT_COMMIT}" -o /out/yq .; \ cp LICENSE /out/licenses/yq/LICENSE; \ /out/yq --version; \ @@ -81,10 +83,10 @@ RUN set -eux; \ test "$(git rev-parse HEAD)" = "${GOMPLATE_GIT_COMMIT}"; \ go get \ github.com/go-git/go-billy/v5@v5.9.0 \ - github.com/go-git/go-git/v5@v5.19.0 \ + github.com/go-git/go-git/v5@v5.19.2 \ golang.org/x/crypto@v0.57.0 \ golang.org/x/net@v0.60.0 \ - google.golang.org/grpc@v1.82.1; \ + google.golang.org/grpc@v1.83.2; \ go mod tidy; \ test "$(go list -m -f '{{.Version}}' golang.org/x/net)" = v0.60.0; \ go build -trimpath -buildvcs=false \ @@ -104,7 +106,10 @@ RUN set -eux; \ test "$(git rev-parse HEAD)" = "${DOCKER_GIT_COMMIT}"; \ cp vendor.mod go.mod; \ cp vendor.sum go.sum; \ - go get golang.org/x/net@v0.60.0; \ + go get golang.org/x/net@v0.60.0 \ + github.com/klauspost/compress@v1.18.7 \ + github.com/moby/go-archive@v0.3.0 \ + google.golang.org/grpc@v1.83.2; \ go mod vendor; \ test "$(go list -m -f '{{.Version}}' golang.org/x/net)" = v0.60.0; \ CGO_ENABLED=0 \ diff --git a/README.md b/README.md index e8c9971..b703a68 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,6 @@ This project is a background service with no user interface or runtime localizat ## October 2026 security maintenance -The source-built gomplate helper selects `golang.org/x/net v0.60.0` for the October HTTP/2 fixes. +The source-built yq, gomplate, and Docker CLI helpers select `golang.org/x/net v0.60.0` for the October HTTP/2 fixes. Their scanned runtime module graph also pins official security fixes: x/text 0.42.0, go-git 5.19.2, grpc-go 1.83.2, klauspost/compress 1.18.7, and moby/go-archive 0.3.0. Upstream helper feature versions stay unchanged; CI exercises the rebuilt helpers and scans the actual final runtime. Maintained Go builds select the patched Go 1.27.3 compiler without raising the existing Go language requirement. Ubuntu build/runtime stages apply the checksum-pinned `ca-certificates 20260816ubuntu0.26.04.1` security package after their frozen APT baseline; the final trust store and installed version are verified. Release artifacts must pass the repository's existing checks before publication.