fix(ci): pin base image digests, verify tool checksums, pin claude-code version #233

Merged
k.renner merged 1 commits from fix/issue-209 into master 2026-07-14 10:54:49 +00:00
Member

Fixes #209.

Changes

  • Digest-pin all base images: ci/images/{ansible,k8s,tofu}/Containerfile (alpine:3.21) and ci/images/claude/Containerfile (node:22-alpine) now pin FROM to the current manifest-list digest, resolved via the Docker Hub registry API at fix time.
  • Checksum-verify tool downloads in ci/images/k8s/Containerfile: talosctl, kubectl, and velero downloads are now verified against their published sha256 checksums before use.
  • Replace curl | bash flux install: swapped for a pinned-version (FLUX_VERSION=2.9.2) tarball download, checksum-verified the same way as the other tools - removes the unpinned fetch-and-execute pattern.
  • Pin kubectl version: previously resolved dynamically from dl.k8s.io/release/stable.txt at build time (floating); added KUBECTL_VERSION=v1.36.2 ARG, matching the existing TALOS_VERSION/VELERO_VERSION pattern. Its checksum is still fetched per-build from dl.k8s.io (immutable per version) and verified.
  • Checksum-verify tofu download in ci/images/tofu/Containerfile.
  • Pin CLAUDE_CODE_VERSION in ci/images/claude/Containerfile from latest to 2.1.209 (current npm latest dist-tag at fix time) - this is the image holding repo/issue-write tokens for the AI agents, so this was the highest-priority item.

All digests/checksums were independently verified against the upstream registries/release APIs (Docker Hub registry v2 API + docker manifest inspect cross-check for image digests; GitHub release asset checksum files for talosctl/velero/tofu/flux; dl.k8s.io's per-version .sha256 file for kubectl; npm registry dist-tags.latest for claude-code).

Note: velero's upstream repo moved from vmware-tanzu/velero to velero-io/velero (GitHub redirects, but I pointed the download URL at the canonical new location since that's also where the checksum file was sourced from).

.woodpecker/build-ci-images.yml needed no changes - it builds with Containerfile ARG defaults and doesn't pass --build-arg overrides, so pinning the defaults directly closes the gap.

Fixes #209. ## Changes - Digest-pin all base images: ci/images/{ansible,k8s,tofu}/Containerfile (alpine:3.21) and ci/images/claude/Containerfile (node:22-alpine) now pin FROM to the current manifest-list digest, resolved via the Docker Hub registry API at fix time. - Checksum-verify tool downloads in ci/images/k8s/Containerfile: talosctl, kubectl, and velero downloads are now verified against their published sha256 checksums before use. - Replace `curl | bash` flux install: swapped for a pinned-version (FLUX_VERSION=2.9.2) tarball download, checksum-verified the same way as the other tools - removes the unpinned fetch-and-execute pattern. - Pin kubectl version: previously resolved dynamically from dl.k8s.io/release/stable.txt at build time (floating); added KUBECTL_VERSION=v1.36.2 ARG, matching the existing TALOS_VERSION/VELERO_VERSION pattern. Its checksum is still fetched per-build from dl.k8s.io (immutable per version) and verified. - Checksum-verify tofu download in ci/images/tofu/Containerfile. - Pin CLAUDE_CODE_VERSION in ci/images/claude/Containerfile from `latest` to 2.1.209 (current npm latest dist-tag at fix time) - this is the image holding repo/issue-write tokens for the AI agents, so this was the highest-priority item. All digests/checksums were independently verified against the upstream registries/release APIs (Docker Hub registry v2 API + `docker manifest inspect` cross-check for image digests; GitHub release asset checksum files for talosctl/velero/tofu/flux; dl.k8s.io's per-version .sha256 file for kubectl; npm registry dist-tags.latest for claude-code). Note: velero's upstream repo moved from vmware-tanzu/velero to velero-io/velero (GitHub redirects, but I pointed the download URL at the canonical new location since that's also where the checksum file was sourced from). `.woodpecker/build-ci-images.yml` needed no changes - it builds with Containerfile ARG defaults and doesn't pass --build-arg overrides, so pinning the defaults directly closes the gap.
claude-bot added 1 commit 2026-07-14 10:11:21 +00:00
fix(ci): pin base image digests, verify tool checksums, pin claude-code version
ci/woodpecker/push/build-ci-images Pipeline was successful
2feec4b193
Addresses #209. All four ci/images/*/Containerfile FROM lines were
tag-pinned only (alpine:3.21, node:22-alpine), letting the base silently
change between builds. Pin each to its current manifest-list digest.

ci/images/k8s/Containerfile downloaded talosctl, kubectl, and velero via
curl with no integrity check, and installed flux via `curl | bash`
(itself an unpinned, unverified fetch-and-execute). Replace the flux
install with a pinned-version tarball download verified against its
published sha256 checksum, same as talosctl/kubectl/velero now are.
kubectl's version was also resolved dynamically from dl.k8s.io's
stable.txt at build time instead of being pinned; add KUBECTL_VERSION.

ci/images/tofu/Containerfile's tofu.zip download gets the same
sha256 verification.

ci/images/claude/Containerfile's CLAUDE_CODE_VERSION defaulted to
`latest` and was never overridden by build-ci-images.yml, so the image
holding repo/issue-write tokens floated to whatever npm resolved at
build time. Pin it to the current release (2.1.209).

Checksums and digests verified against the respective registries/release
APIs at fix time (2026-07-14).

Co-Authored-By: Claude Bot <claude-bot@renner.uno>
k.renner merged commit 5681da8ccd into master 2026-07-14 10:54:49 +00:00
Sign in to join this conversation.