Skip to content

fix: patch base-image vulnerabilities; correct multi-arch; safer tags + CI#43

Merged
maniator merged 5 commits into
mainfrom
fix/bump-base-image-vulnerabilities
Jun 19, 2026
Merged

fix: patch base-image vulnerabilities; correct multi-arch; safer tags + CI#43
maniator merged 5 commits into
mainfrom
fix/bump-base-image-vulnerabilities

Conversation

@maniator

@maniator maniator commented Jun 19, 2026

Copy link
Copy Markdown
Owner

Why

maniator/gh (~624k pulls) ships on a pinned, increasingly stale Alpine base (what Snyk / Docker Scout flag), and along the way this surfaced a multi-arch binary bug. This patches the base, fixes the binary bug, gives version-pinning consumers a non-breaking path to security updates, and adds CI to catch regressions.

What

Base-image / CVE fixes — apply to latest and all future builds, zero breakage:

  • Alpine 3.21.33.24.1 in both stages + apk upgrade --no-cache
  • Default GH_VERSION 2.10.12.95.0 (CI still fetches real latest via set_tags)

Multi-arch correctness (real bug; supersedes #42):

  • Download the gh release for TARGETPLATFORM, not BUILDPLATFORM — arm64/arm images were shipping the amd64 binary. gh asset names don't map 1:1 to Docker platforms (linux/arm64/v8linux_arm64; no armv7 build, armv6 runs on armv7), so they're mapped explicitly. Verified with a linux/amd64,linux/arm64,linux/arm/v7 buildx build.

Tag strategy — protect pinners without breaking reproducibility:

  • Rolling vMAJOR / vMAJOR.MINOR (v2, v2.95) + latest move on the patched base, only when building the newest release.
  • Exact vX.Y.Z tags are immutable by default (published once; nightly no longer republishes them).
  • REBUILD_EXACT=1 (workflow_dispatch input) force-refreshes recent exact tags on the patched base; hooks/scripts/rebuild_recent does the latest N=3. Older tags stay frozen.
  • README documents the moving / rolling / immutable scheme.

New PR-validation workflows (parity with dind-buildx + vuln focus):

  • Trivy image scan (PR + weekly), hadolint (+ .hadolint.yaml), shellcheck, dependabot (base image + Actions).

Report: downstream-usage-report.md — consumer exposure (gh search code) + Docker Hub tag_last_pulled analysis.

Verification

  • docker buildgh version 2.95.0; multi-arch buildx confirms each platform pulls its own gh_2.95.0_linux_<arch>.tar.gz.
  • set_tags validated against the live registry: newest build emits rolling tags only (leaves v2.95.0 untouched); a missing version emits its exact tag; REBUILD_EXACT=1 forces it.
  • hadolint + shellcheck run clean locally; all workflow YAML validated.

Addresses the Copilot + Codex review comments below.

🤖 Generated with Claude Code

Copilot AI review requested due to automatic review settings June 19, 2026 22:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the maniator/gh Docker image to reduce vulnerability scanner findings by refreshing the Alpine base and ensuring packages are upgraded, and introduces an opt-in rolling tag scheme (vMAJOR, vMAJOR.MINOR) to let consumers receive base-image security updates without relying on mutable rebuilds of fully-qualified vX.Y.Z pins.

Changes:

  • Bump the Docker base image (both stages) to Alpine 3.24.1 and run apk upgrade --no-cache during builds.
  • Update the default GH_VERSION build arg and adjust set_tags to publish rolling tags only for the newest upstream gh release.
  • Document the tag immutability/rolling scheme in README.md and add a downstream usage/exposure report.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 2 comments.

File Description
Dockerfile Updates Alpine base image and adds apk upgrade; updates default GH_VERSION.
hooks/scripts/set_tags Adds guard logic intended to only move rolling tags on newest release builds.
README.md Documents rolling vs immutable tags and pinning guidance.
downstream-usage-report.md Adds a report summarizing downstream pinning exposure and tag recency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Dockerfile Outdated
Comment thread hooks/scripts/set_tags

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 95762adbd8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread README.md Outdated
@maniator maniator force-pushed the fix/bump-base-image-vulnerabilities branch from 95762ad to 75f4895 Compare June 19, 2026 22:58
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@maniator

Copy link
Copy Markdown
Owner Author

Thanks for the automated reviews — all three points are addressed in the latest push:

  1. Multi-arch binary (Copilot) — fixed. The builder now derives the asset from TARGETPLATFORM with an explicit map (linux/arm64/v8 → linux_arm64, linux/arm/v7 → linux_armv6, since gh ships no armv7 build), instead of BUILDPLATFORM. Verified with a linux/amd64,linux/arm64,linux/arm/v7 buildx build — each platform now downloads its own gh_2.95.0_linux_<arch>.tar.gz. (This is a superset of fix: download github CLI for target platform #42, which used the raw ${TARGETPLATFORM//\//_} substitution and would 404 on arm — e.g. linux_arm64_v8.)

  2. set_tags rewriting vX.Y.Z / 3. README immutability promise (Codex) — fixed and made consistent. The nightly job no longer republishes the exact tag: set_tags only includes maniator/gh:v${GH_VERSION} when it doesn't already exist on Docker Hub, so a pin like v2.95.0 stays byte-for-byte reproducible while only the rolling latest/v2/v2.95 tags move on the patched base. A deliberate, opt-in REBUILD_EXACT=1 (workflow_dispatch input) force-refreshes the most recent few releases on the patched base (hooks/scripts/rebuild_recent, N=3); older tags stay frozen. README/report updated to describe exactly this.

Also added Trivy / hadolint / shellcheck / dependabot workflows so regressions get caught on future PRs.

Comment thread .github/workflows/hadolint.yml Fixed
Comment thread .github/workflows/shell-check.yml Fixed
Comment thread .github/workflows/trivy.yml Fixed
@maniator maniator changed the title fix: patch base-image vulnerabilities; add opt-in rolling tags fix: patch base-image vulnerabilities; correct multi-arch; safer tags + CI Jun 19, 2026
@maniator maniator force-pushed the fix/bump-base-image-vulnerabilities branch from 75f4895 to ed171ba Compare June 19, 2026 23:09
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

…; CI

Base image / CVE fixes (apply to `latest` and all future builds — no breakage):
- Bump Alpine 3.21.3 -> 3.24.1 in both build stages
- Add `apk upgrade --no-cache` to pull OS package security patches
- Bump default GH_VERSION 2.10.1 -> 2.95.0 (CI still overrides with latest)

Multi-arch correctness (fixes a real bug; supersedes #42):
- Download the gh release for TARGETPLATFORM, not BUILDPLATFORM, so arm64/arm
  images stop shipping the amd64 binary. gh asset names don't map 1:1 to Docker
  platforms (linux/arm64/v8 -> linux_arm64; no armv7 build, armv6 runs on armv7),
  so map them explicitly. Verified by a linux/amd64+arm64+arm/v7 buildx build.

Tag strategy — protect pinners without breaking reproducibility:
- set_tags publishes rolling `vMAJOR`/`vMAJOR.MINOR` (e.g. v2, v2.95) + `latest`,
  only when building the newest release.
- Exact `vX.Y.Z` tags are immutable by default (published once); the nightly job
  no longer republishes them, so a pin stays byte-for-byte reproducible.
- REBUILD_EXACT=1 (workflow_dispatch input) force-refreshes a recent exact tag on
  the patched base; hooks/scripts/rebuild_recent does this for the latest N=3.
- README documents the scheme.

New PR-validation workflows (parity with dind-buildx + vuln focus):
- Trivy image scan (PR + weekly), hadolint (+ .hadolint.yaml), shellcheck,
  and dependabot for the base image and Actions.

Add downstream-usage-report.md: consumer exposure + Docker Hub tag_last_pulled.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@maniator maniator force-pushed the fix/bump-base-image-vulnerabilities branch from ed171ba to f5ce245 Compare June 19, 2026 23:17
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@maniator

Copy link
Copy Markdown
Owner Author

Resolved the remaining review threads:

  • CodeQL — "workflow does not contain permissions" (hadolint / shell-check / trivy): added explicit least-privilege permissions: blocks (contents: read; pull-requests: write for shellcheck's reviewdog reporter), and contents: write on the build/release workflow for the gh release create step. CodeQL dismissed the alerts on the re-run.
  • The earlier Copilot/Codex threads (multi-arch BUILDPLATFORM, set_tags republishing exact tags, README immutability) were addressed in prior commits and are now marked resolved.

Automates the recent-pin security refresh: a matrix job rebuilds the latest 3
exact vX.Y.Z tags on the current patched base (set_tags + bake, REBUILD_EXACT=1),
weekly and on demand. Runs the build directly rather than dispatching "Build and
Release", since a GITHUB_TOKEN-triggered workflow_dispatch wouldn't start a run.
hooks/scripts/rebuild_recent remains for ad-hoc local runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 4 comments.

Comment thread .github/workflows/shell-check.yml
Comment thread .github/workflows/docker-build.yml Outdated
Comment thread .github/workflows/trivy.yml
Comment thread hooks/scripts/set_tags
…tags

- Split release into its own job with contents: write; the workflow now defaults
  to contents: read so PR-triggered build steps don't carry a write-capable token
- set_tags emits skip=true when there's nothing to publish (exact tag already
  exists and REBUILD_EXACT unset, non-newest); build/release are gated on it so
  the run no longer produces an empty tag list and a silent no-op push
- shell-check: use the canonical ${{ github.token }} for reviewdog auth

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@maniator

Copy link
Copy Markdown
Owner Author

Thanks Copilot — addressed the new round:

  1. shell-check secrets.github_token → switched to the canonical ${{ github.token }} (the job already grants pull-requests: write for reviewdog's PR reporter).
  2. docker-build.yml contents: write on PRs → split release into its own job with permissions: contents: write; the workflow now defaults to contents: read, so the PR-triggered build steps no longer carry a write-capable token.
  3. set_tags empty-tags no-opset_tags now emits skip=true when there's nothing to publish (exact tag already exists and REBUILD_EXACT unset on a non-newest version); the build and release steps are gated on it, so no more empty tag list / silent no-op push.
  4. Pin trivy-action to a SHA → fair point for security tooling, but intentionally keeping the tag pin: every action in this repo is tag-pinned (docker/*, hadolint, reviewdog, checkout, metadata), and this PR adds Dependabot for github-actions, which keeps those tags patched. SHA-pinning just Trivy would be inconsistent and give a false sense of hardening; a repo-wide SHA-pin policy is a separate change. Resolving on that basis.

Quote the gh tarball path/URL expansions (SC2086) and add wget -q (DL3047)
so hadolint reports zero findings and stops annotating the diff. No behavior
change; image still builds gh 2.95.0 across platforms.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 3 comments.

Comment thread hooks/scripts/set_tags
Comment thread .github/workflows/refresh-recent-tags.yml Outdated
Comment thread hooks/scripts/set_tags
@maniator maniator requested a review from Copilot June 19, 2026 23:39

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Comment thread hooks/scripts/set_tags
Comment thread hooks/scripts/set_tags
- set_tags: resolve VERSION from the latest *stable* gh release (skip
  drafts/prereleases) so rolling tags aren't suppressed or moved onto a
  prerelease; validate GH_VERSION matches X.Y.Z before interpolating it into
  the Docker Hub URL and bake tags (rejects malformed/injected values)
- refresh-recent-tags: fetch releases with `curl -fsS --retry` + github.token
  auth so the matrix step fails fast instead of feeding bad JSON to fromJson

Verified set_tags across nightly/dispatch/rebuild/invalid cases; build path
unchanged for the normal (newest-release) flow.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@maniator

Copy link
Copy Markdown
Owner Author

Addressed this round:

  1. set_tags VERSION could be a draft/prerelease → now resolves the latest stable release: jq '[ .[] | select(.prerelease==false and .draft==false) | .tag_name ][0]'. Rolling tags can no longer be suppressed or moved onto a prerelease.
  2. refresh-recent-tags curl -s swallows HTTP errors → switched to curl -fsS --retry 3 with Authorization: Bearer ${{ github.token }}, so the matrix step fails fast (with a message) instead of feeding empty/invalid JSON to fromJson.
  3. GH_VERSION interpolated without validation → added grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+$'; a non-X.Y.Z value now aborts the build before it can touch the Docker Hub URL or the bake tags. Verified it rejects e.g. 2.95.0; rm -rf /.

Also traced/tested the nightly + push + dispatch + rebuild paths against these changes — the normal newest-release flow still emits skip=false with the rolling tags and a valid version.

@maniator maniator merged commit 9b805f1 into main Jun 19, 2026
7 checks passed
@maniator maniator deleted the fix/bump-base-image-vulnerabilities branch June 19, 2026 23:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants