[security][medium] CI images unpinned (no digest), curl|bash installs, ci-claude tracks @latest #209

Closed
opened 2026-07-14 09:49:13 +00:00 by claude-bot · 1 comment
Member

Finding

  • ci/images/*/Containerfile use tag-pinned (not digest-pinned) bases: alpine:3.21, node:22-alpine.
  • ci/images/k8s/Containerfile: 'curl -sfL https://fluxcd.io/install.sh | bash', and talosctl/kubectl/tofu downloaded via curl with no checksum/signature verification.
  • ci/images/claude/Containerfile: ARG CLAUDE_CODE_VERSION=latest, never overridden by build-ci-images.yml — the image that runs the two token-holding AI agents floats to whatever npm resolves at build time.

Verified

Cited Containerfiles; build-ci-images.yml does not pin the claude version.

Impact

Silent upstream replacement of any base/tool; highest concern is ci-claude since it holds repo/issue-write tokens.

Fix

Pin bases by digest; verify checksums/signatures for tool downloads; pin CLAUDE_CODE_VERSION.


Automated security review 2026-07-14. Verified.

## Finding - ci/images/*/Containerfile use tag-pinned (not digest-pinned) bases: alpine:3.21, node:22-alpine. - ci/images/k8s/Containerfile: 'curl -sfL https://fluxcd.io/install.sh | bash', and talosctl/kubectl/tofu downloaded via curl with no checksum/signature verification. - ci/images/claude/Containerfile: ARG CLAUDE_CODE_VERSION=latest, never overridden by build-ci-images.yml — the image that runs the two token-holding AI agents floats to whatever npm resolves at build time. ## Verified Cited Containerfiles; build-ci-images.yml does not pin the claude version. ## Impact Silent upstream replacement of any base/tool; highest concern is ci-claude since it holds repo/issue-write tokens. ## Fix Pin bases by digest; verify checksums/signatures for tool downloads; pin CLAUDE_CODE_VERSION. --- _Automated security review 2026-07-14. Verified._
Author
Member

Fixed in PR #233 (branch fix/issue-209).

Verified all findings against origin/master at 07c93e4 before fixing:

  • ci/images/{ansible,k8s,tofu}/Containerfile: FROM alpine:3.21 was tag-only -> pinned to sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d (current manifest-list digest, cross-checked via registry API and 'docker manifest inspect').
  • ci/images/claude/Containerfile: FROM node:22-alpine -> pinned to sha256:16e22a550f3863206a3f701448c45f7912c6896a62de43add43bb9c86130c3e2; CLAUDE_CODE_VERSION=latest -> pinned to 2.1.209 (current npm latest dist-tag). This was the highest-priority item since ci-claude holds repo/issue-write tokens.
  • ci/images/k8s/Containerfile: talosctl, kubectl, and velero downloads now checksum-verified (sha256sum -c) against each project's published checksum file. 'curl fluxcd.io/install.sh | bash' replaced with a pinned-version (2.9.2), checksum-verified tarball download - removes the curl|bash fetch-and-execute pattern entirely. kubectl's version, previously resolved dynamically from dl.k8s.io/release/stable.txt at build time, is now pinned via KUBECTL_VERSION=v1.36.2 (its checksum is still fetched per-build from dl.k8s.io, which is immutable per version, and verified).
  • ci/images/tofu/Containerfile: tofu.zip download now checksum-verified.
  • .woodpecker/build-ci-images.yml needed no changes - it builds with Containerfile ARG defaults (no --build-arg overrides), so pinning the defaults directly closes the gap.

Note: velero's upstream repo moved from vmware-tanzu/velero to velero-io/velero (old URL still redirects, but I pointed the download at the canonical new location, matching where I sourced the checksum).

PR: gitea_admin/homelab#233

Fixed in PR #233 (branch fix/issue-209). Verified all findings against origin/master at 07c93e4 before fixing: - ci/images/{ansible,k8s,tofu}/Containerfile: FROM alpine:3.21 was tag-only -> pinned to sha256:48b0309ca019d89d40f670aa1bc06e426dc0931948452e8491e3d65087abc07d (current manifest-list digest, cross-checked via registry API and 'docker manifest inspect'). - ci/images/claude/Containerfile: FROM node:22-alpine -> pinned to sha256:16e22a550f3863206a3f701448c45f7912c6896a62de43add43bb9c86130c3e2; CLAUDE_CODE_VERSION=latest -> pinned to 2.1.209 (current npm latest dist-tag). This was the highest-priority item since ci-claude holds repo/issue-write tokens. - ci/images/k8s/Containerfile: talosctl, kubectl, and velero downloads now checksum-verified (sha256sum -c) against each project's published checksum file. 'curl fluxcd.io/install.sh | bash' replaced with a pinned-version (2.9.2), checksum-verified tarball download - removes the curl|bash fetch-and-execute pattern entirely. kubectl's version, previously resolved dynamically from dl.k8s.io/release/stable.txt at build time, is now pinned via KUBECTL_VERSION=v1.36.2 (its checksum is still fetched per-build from dl.k8s.io, which is immutable per version, and verified). - ci/images/tofu/Containerfile: tofu.zip download now checksum-verified. - .woodpecker/build-ci-images.yml needed no changes - it builds with Containerfile ARG defaults (no --build-arg overrides), so pinning the defaults directly closes the gap. Note: velero's upstream repo moved from vmware-tanzu/velero to velero-io/velero (old URL still redirects, but I pointed the download at the canonical new location, matching where I sourced the checksum). PR: https://gitea.renner.uno/gitea_admin/homelab/pulls/233
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: konairius/homelab#209