Stack (DEP-91)
Split from #1662 for reviewability, then rescoped: main has since landed #1681 (dependency/toolchain CVEs) and #1693 (hoophq/hoopagent), which superseded two PRs of the original stack.
-
#1683 — Go dependency + toolchain CVE bumps— closed, superseded by #1681 -
#1685 — opt-in— closed, superseded by #1693hoophq/hoopdev-minimal -
#1684 — 1. agent-tools: drop kernel-header CVEs, modernize clean train
-
#1686 — 2. Vulnerability gates for hoopagent + govulncheck
-
#1687 — 3. SBOM + bundled-tool manifest on releases
-
#1688 — 4. Weekly base-OS rebuild of hoopagent
-
#1689 — 5. Image release integrity hardening ← you are here
Merge in order, bottom-up. Each PR targets the one below it.
The remaining work is what main still lacks: the fat image's kernel-header CVEs, and any vulnerability gate, SBOM, or scheduled OS patching for hoophq/hoopagent.
What
Hardens how images and release artifacts are published:
- Verified, reviewed checksums for hand-installed binaries (fails closed on missing, duplicate, or mismatched digests)
- Immutable candidate promotion — gate before push, so a partial multiarch manifest can never be promoted
- Digest-pinned actions and scanner images
- Bundled-tool versions read from immutable image labels rather than re-parsed at release time
- Second
govulncheckjob forhsh-tunneld, which ships from its own Go module and is not reachable from the client module's package graph
Why
Final layer: the supply chain should fail closed rather than publish something unverified.
Risk
Highest-surface PR in the stack (release workflow), which is why it merges last — everything below is green by then.
How to test
python3 -m unittest scripts/ci/test_generate_sbom_manifest.py
nix-shell -p actionlint --run 'actionlint .github/workflows/release.yml'Expected: tests pass. Remaining actionlint findings (GitHub-Linux-Arm-Runner label, merge-archive) are pre-existing on main on lines this PR does not touch.
Part of DEP-91.
Automated by MisterMal
Activity
11Code Review by Qodo
🐞 Bugs (1) 📘 Rule violations (0) 📎 Requirement gaps (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)
1. No retries on downloads 🐞 Bug ☼ Reliability
Description
Dockerfile.tools switched kubectl/aws/sqlcmd downloads to fail-closed curl --fail, but the new download commands have no bounded retry policy, so transient CDN/network failures will now fail the Docker build immediately and can cause avoidable CI/release flakiness.
Code
+ && curl --fail --location --silent --show-error \ + --proto '=https' --tlsv1.2 \ + "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${dpkgArch}/kubectl" \ + --output "$artifact" \
Relevance
●●● StrongBounded curl retries reduce CI flakiness; similar Dockerfile.tools reliability hardening suggestions were accepted.
ⓘ Recommendations generated based on similar findings in past PRs
Evidence
The new kubectl download uses curl --fail ... but no --retry, and the same pattern is used for other manual downloads (AWS CLI zip and sqlcmd tarball). In contrast, the weekly rebuild workflow already uses curl --retry 3 --retry-all-errors for integrity-critical downloads, showing an established repo pattern for bounded resilience.
Dockerfile.tools[123-155]Dockerfile.tools[195-215].github/workflows/minimal-image-rebuild.yml[121-134]
Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution ### Issue description `Dockerfile.tools` now downloads kubectl/AWS CLI/sqlcmd using `curl --fail --location --silent --show-error` (good: fail-closed), but without `--retry` this makes the build brittle to transient network/CDN issues. ### Issue Context This PR hardened integrity checks for manually downloaded binaries. To keep builds reliable, the download step should also be resilient. Other integrity-critical download paths in CI already use bounded retries. ### Fix Focus Areas - Dockerfile.tools[127-155] - Dockerfile.tools[205-213]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Context
39 rules✅ Cross-repo context
repo: hoophq/infra (sha: 801e2c0a)hoophq/libhoophoophq/documentationhoophq/changelogTip of the day
💡 Did you know, you can enable the Remediation agent and Qodo fixes findings in a dedicated fix PRMore tips ↗ | Customize Qodo ↗ | Qodo docs ↗
Migration Safety Analysis
No database migrations were changed in this PR. Safe to deploy to sandbox.
✅ Build Completed with Success, Version=1689.0.0-gf73d1b1
✅ Build Completed with Success, Version=1689.0.0-g42c1f19
PR Summary by Qodo
DEP-91 (7/7): Harden image release integrity end-to-end
✨ Enhancement⚙️ Configuration changes🧪 Tests🕐 40+ MinutesAI Description
Diagram
High-Level Assessment
Files changed (16)
+857 / -288Enhancement (5)
+475 / -260minimal-image-rebuild.yml
Restructure weekly rebuild to trust GitHub Release digests and gate-before-push per arch+152/-56pullrequest.yml
Run new CI helper tests and add govulncheck for hsh-tunneld+15/-4release.yml
Gate hoopdev-minimal per-arch, pin actions, and harden SBOM/release-asset steps+159/-133Dockerfile.tools
Verify manual downloads against reviewed checksums and add provenance labels+55/-16generate-sbom-manifest.py
Make SBOM generation fail closed for required images and read tool versions from image labels+94/-51Tests (1)
+54 / -0test_generate_sbom_manifest.py
Add unit tests for SBOM generator subprocess handling+54/-0Documentation (2)
+3 / -1custom-agent-image.md
Update release-tag mutability documentation+1/-1manual-binaries.toml
Cross-reference new checksum manifest+2/-0Other (8)
+325 / -27agent-tools-build.yml
Pin actions/scanners by digest and defer Docker Hub login until after scan+27/-19minimal-image-build.yml
Pin PR-smoke build actions and Trivy scanner+8/-6pullrequest-release.yml
Pin Trivy scanner image by digest+1/-1Dockerfile.minimal
Pin base image by digest+1/-1agent-tools-checksums.sha256
Add reviewed checksum manifest for hand-installed tool archives+16/-0legacy-release-checksums.sha256
Add reviewed bootstrap checksum pins for pre-DEP-91 releases+5/-0report-agent-tools-versions.py
Add script to probe and pin exact agent-tools base image metadata+190/-0verify-manual-download.py
Add checksum verification script for manually downloaded binaries+77/-0