security: harden container supply chain - #17
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: 📒 Files selected for processing (14)
📜 Recent review details🧰 Additional context used📓 Path-based instructions (4)scripts/**/*.sh⚙️ CodeRabbit configuration file
Files:
images/**/Dockerfile⚙️ CodeRabbit configuration file
Files:
**/*.md⚙️ CodeRabbit configuration file
Files:
.github/workflows/**⚙️ CodeRabbit configuration file
Files:
🪛 actionlint (1.7.12).github/workflows/publish-edge-amd64.yml[error] 65-65: shellcheck reported issue in this script: SC2129:style:2:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects (shellcheck) 🪛 Checkov (3.3.8)images/codex/Dockerfile[low] 3-3: Ensure the base image uses a non latest version tag (CKV_DOCKER_7) [low] 1-94: Ensure that a user for the container has been created (CKV_DOCKER_3) images/base/Dockerfile[low] 1-173: Ensure that HEALTHCHECK instructions have been added to container images (CKV_DOCKER_2) [low] 1-173: Ensure that a user for the container has been created (CKV_DOCKER_3) 🪛 Hadolint (2.14.0)images/codex/Dockerfile[warning] 37-37: Use WORKDIR to switch to a directory (DL3003) images/base/Dockerfile[warning] 57-57: Pin versions in apt get install. Instead of (DL3008) [warning] 103-103: Use WORKDIR to switch to a directory (DL3003) [warning] 120-120: Use WORKDIR to switch to a directory (DL3003) [warning] 136-136: Use WORKDIR to switch to a directory (DL3003) 🪛 LanguageToolCHANGELOG.md[style] ~40-~40: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym. (ENGLISH_WORD_REPEAT_BEGINNING_RULE) [style] ~41-~41: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym. (ENGLISH_WORD_REPEAT_BEGINNING_RULE) 🪛 Shellcheck (0.11.0)scripts/validate-version-pins.sh[info] 97-97: Expressions don't expand in single quotes, use double quotes for that. (SC2016) 🔇 Additional comments (24)
Summary by CodeRabbit
WalkthroughThe change adds immutable version, image, action, frontend, and asset checksum pins; synchronizes them through upstream automation and publishing workflows; verifies them during Docker builds; and gates image publication and AMD64 builds on Trivy findings. ChangesSupply-chain integrity and build automation
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant check-upstream.yml
participant GitHubReleases
participant versions.env
participant validate-version-pins.sh
participant AutomationPR
check-upstream.yml->>GitHubReleases: fetch constrained release tags and asset digests
check-upstream.yml->>versions.env: update versions and SHA256 values
check-upstream.yml->>validate-version-pins.sh: validate synchronized pins
validate-version-pins.sh-->>check-upstream.yml: return validation result
check-upstream.yml->>AutomationPR: create or update automation PR
sequenceDiagram
participant publish-workflows
participant ContainerRegistry
participant Trivy
participant enforce-trivy-gate.sh
participant PublicTags
publish-workflows->>ContainerRegistry: push base and Codex candidates by digest
publish-workflows->>Trivy: scan exact candidate digests
Trivy-->>publish-workflows: return JSON reports
publish-workflows->>enforce-trivy-gate.sh: enforce fixable CRITICAL gate
enforce-trivy-gate.sh-->>publish-workflows: return gate result
publish-workflows->>PublicTags: promote matching scanned digests
PublicTags-->>publish-workflows: verify promoted digests
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
There was a problem hiding this comment.
Actionable comments posted: 7
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/build-amd64.yml:
- Around line 75-111: Extract the vulnerability-gate logic from the workflow
step into a shared executable scripts/enforce-trivy-gate.sh accepting one or
more label:report arguments, preserving its jq filtering, diagnostics, findings
aggregation, and failure behavior. Replace the duplicated blocks in
build-amd64.yml, publish-amd64.yml, and publish-edge-amd64.yml with calls to the
shared script using each workflow’s existing labels and report filenames, and
ensure it is included in the existing bash -n validation loop.
- Around line 64-74: Update the Trivy report upload steps to avoid turning
missing reports into misleading failures: in .github/workflows/build-amd64.yml
lines 64-74, .github/workflows/publish-amd64.yml lines 166-176, and
.github/workflows/publish-edge-amd64.yml lines 166-176, gate each upload with
!cancelled() or change if-no-files-found to warn while preserving report uploads
when scans produce files.
In @.github/workflows/check-upstream.yml:
- Around line 151-162: Make replace_env and replace_arg fail when their target
key is absent instead of allowing sed to silently succeed without a match.
Before or during each replacement, verify that the expected variable or ARG
exists in the target file, return a nonzero status with a clear error if it does
not, and preserve the current replacement behavior when the key is present so
the workflow cannot incorrectly close the automation PR.
In @.github/workflows/publish-amd64.yml:
- Around line 24-26: Add persist-credentials: false to the checkout steps in
.github/workflows/publish-amd64.yml (lines 24-26),
.github/workflows/publish-edge-amd64.yml (line 33), and
.github/workflows/build-amd64.yml (lines 18-22). In publish-amd64.yml, preserve
the later authenticated git fetch by passing an explicit token to that fetch
when the repository is private; no follow-up authentication change is needed in
the other workflows.
In `@images/base/Dockerfile`:
- Around line 100-140: The architecture selection and release downloads need
stricter handling. In images/base/Dockerfile lines 100-140, update the gh, ttyd,
and mise case statements to use TARGETARCH without an amd64 fallback, and add
the specified retry, connect-timeout, and max-time options to each curl
invocation. In images/codex/Dockerfile lines 37-45, make the same TARGETARCH
change and apply the same curl bounds to the Codex download.
In `@scripts/validate-version-pins.sh`:
- Around line 156-173: Update the version-pin contract around the sync loop by
adding BASE_VERSION to the variables passed to require_synced_arg, keeping it
synchronized between versions.env and images/base/Dockerfile. For
BUBBLEWRAP_VERSION, remove the exact apt version pin from the base image
Dockerfile so installation follows the digest-pinned base image, unless you
instead add it to versions.env with a maintainable update path.
- Around line 103-106: Update the UBUNTU_VERSION validation in the
version-pinning script to require the same even-year .04 Ubuntu LTS pattern
enforced by renovate.json, rejecting interim releases such as 25.04 while
preserving the existing error and exit behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 9cc90105-1a48-4c84-aba3-bfbf331710e7
📒 Files selected for processing (12)
.github/workflows/build-amd64.yml.github/workflows/check-upstream.yml.github/workflows/publish-amd64.yml.github/workflows/publish-edge-amd64.ymlCHANGELOG.mdPROJECT_STATUS.mdimages/base/Dockerfileimages/codex/Dockerfilerenovate.jsonscripts/build-local.shscripts/validate-version-pins.shversions.env
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
**/*.md
⚙️ CodeRabbit configuration file
**/*.md: Check that documentation matches the implemented behavior and clearly distinguishes experimental edge builds
from stable releases. Flag outdated versions, unsafe deployment guidance and claims not proven by CI or testing.
Files:
PROJECT_STATUS.mdCHANGELOG.md
scripts/**/*.sh
⚙️ CodeRabbit configuration file
scripts/**/*.sh: Review as production Bash. Check quoting, set -euo pipefail behavior, cleanup traps,
bounded retries and timeouts, non-interactive execution, idempotency and useful failure messages.
Flag commands that can hang, leak credentials, silently ignore failures or mutate persistent data unexpectedly.
Files:
scripts/build-local.shscripts/validate-version-pins.sh
images/**/Dockerfile
⚙️ CodeRabbit configuration file
images/**/Dockerfile: Review for reproducibility, supply-chain security and minimal image growth.
Require pinned upstream versions and checksum or digest verification for downloaded binaries.
Flag secrets, floating base tags, unsafe remote-script execution, broken multi-architecture logic,
cache misuse, unnecessary packages and changes that weaken the secure-by-default runtime.
Files:
images/codex/Dockerfileimages/base/Dockerfile
.github/workflows/**
⚙️ CodeRabbit configuration file
.github/workflows/**: Review GitHub Actions for least-privilege permissions, safe event triggers, untrusted input handling,
accidental publication, tag-channel correctness, secret exposure, reproducible builds, SBOM/provenance
generation and appropriate validation before pushing images.
Files:
.github/workflows/build-amd64.yml.github/workflows/check-upstream.yml.github/workflows/publish-edge-amd64.yml.github/workflows/publish-amd64.yml
🪛 actionlint (1.7.12)
.github/workflows/publish-edge-amd64.yml
[error] 65-65: shellcheck reported issue in this script: SC2129:style:2:1: Consider using { cmd1; cmd2; } >> file instead of individual redirects
(shellcheck)
🪛 Checkov (3.3.8)
images/codex/Dockerfile
[low] 3-3: Ensure the base image uses a non latest version tag
(CKV_DOCKER_7)
[low] 1-93: Ensure that a user for the container has been created
(CKV_DOCKER_3)
images/base/Dockerfile
[low] 1-167: Ensure that HEALTHCHECK instructions have been added to container images
(CKV_DOCKER_2)
[low] 1-167: Ensure that a user for the container has been created
(CKV_DOCKER_3)
🪛 Hadolint (2.14.0)
images/codex/Dockerfile
[warning] 37-37: Use WORKDIR to switch to a directory
(DL3003)
images/base/Dockerfile
[warning] 100-100: Use WORKDIR to switch to a directory
(DL3003)
[warning] 116-116: Use WORKDIR to switch to a directory
(DL3003)
[warning] 131-131: Use WORKDIR to switch to a directory
(DL3003)
🪛 LanguageTool
CHANGELOG.md
[style] ~40-~40: Three successive sentences begin with the same word. Consider rewording the sentence or use a thesaurus to find a synonym.
Context: ...matically after required checks pass. - Changed the bubblewrap runtime probe to report ...
(ENGLISH_WORD_REPEAT_BEGINNING_RULE)
🪛 Shellcheck (0.11.0)
scripts/validate-version-pins.sh
[info] 97-97: Expressions don't expand in single quotes, use double quotes for that.
(SC2016)
🪛 zizmor (1.26.1)
.github/workflows/check-upstream.yml
[warning] 17-19: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
.github/workflows/publish-edge-amd64.yml
[warning] 33-33: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
.github/workflows/publish-amd64.yml
[warning] 24-26: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false
(artipacked)
🔇 Additional comments (28)
renovate.json (1)
4-32: LGTM!Also applies to: 48-58
scripts/validate-version-pins.sh (4)
62-89: LGTM!
91-101: LGTM! The SC2016 hint on Line 97 is a false positive — the literal${UBUNTU_VERSION}string is exactly what must appear in the Dockerfile.
182-188: LGTM!
49-60: 🎯 Functional CorrectnessNo change needed.
scripts/validate-version-pins.shusesset -euo pipefail, soexit 1fromrequire_frontend_pinterminates the script viaerrexitafter the command-substitution assignment fails.images/base/Dockerfile (2)
1-29: LGTM!
152-155: LGTM! The explicitnpm --versionassertion is a good guard against the shim resolving to the Node-bundled npm.scripts/build-local.sh (2)
67-68: LGTM!
45-58: 🗄️ Data Integrity & IntegrationNo change needed.
UBUNTU_VERSIONandUV_VERSIONare already passed throughscripts/build-local.sh, and the base image ARGs are covered by the local build args..github/workflows/check-upstream.yml (4)
17-19: LGTM! The zizmorartipackedhint is a false positive — this job pushes the automation branch with the checkout credentials at Line 218, sopersist-credentials: falsewould break it.
28-62: LGTM! Each derived value is regex-validated at Lines 64-95 before it reaches thesedreplacements, so no unvalidated upstream string is interpolated into the pin files.
97-136: LGTM! Thetrap-based cleanup, the.digest-then-SHA256SUMSfallback, and the hard failure on an unresolvable digest are all correct; the awk$2 == "*" assetconcatenation properly handles binary-mode checksum lines.
221-256: LGTM!--jq '.[0] // {}'correctly yields an empty object when no run matches, so the three// emptyextractions degrade to empty strings and the dispatch branch at Line 258 fires.PROJECT_STATUS.md (1)
11-11: LGTM! Every listed pin matchesversions.env, and the review date is consistent across both files.Also applies to: 40-54
versions.env (1)
21-25: 🗄️ Data Integrity & IntegrationPins are valid stable releases.
.github/workflows/publish-amd64.yml (6)
52-58: LGTM!
64-86: LGTM!
88-118: LGTM!
120-131: LGTM!Also applies to: 154-165
132-153: LGTM!
177-251: LGTM!.github/workflows/publish-edge-amd64.yml (3)
55-86: LGTM!
88-165: LGTM!
177-250: LGTM!CHANGELOG.md (3)
14-14: LGTM!
27-27: LGTM!
57-59: LGTM!.github/workflows/build-amd64.yml (1)
39-63: 📐 Maintainability & Code QualityNo change needed.
The hardcoded Trivy
image-refvalues match the defaultBASE_IMAGEandCODEX_IMAGEproduced byscripts/build-local.sh.
|
@coderabbitai full review |
✅ Action performedFull review finished. Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 4 minutes. |
|
Codex Review: Didn't find any major issues. Hooray! Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
|
@coderabbitai full review |
✅ Action performedFull review finished. |
What changed
CRITICALfindings for 14 days.scripts/enforce-trivy-gate.shso build, edge and stable workflows use the same policy.versions.env, Dockerfiles, local builds and publication workflows.2026.7.14, Node.js24.18.0LTS, npm12.0.1and uv0.11.32; Codex0.145.0, Python3.14.6, GitHub CLI2.96.0and ttyd1.7.7were already current.SHA256SUMSasset when GitHub does not expose an asset digest, as currently happens with ttyd.TARGETARCHis missing or unsupported.Bubblewrap
The image previously pinned
bubblewrapto the exact Ubuntu package revision0.11.1-1ubuntu0.1. That looked reproducible, but Ubuntu repositories normally remove superseded package revisions. A future security update could therefore make an unchanged Dockerfile permanently fail because the old.debwas no longer available.This PR now installs
bubblewrapwithout an exact APT revision, selecting the current security revision from the repositories configured by Ubuntu 26.04. Repository validation prevents an exact bubblewrap package pin from being reintroduced unless the project first adopts an APT snapshot strategy.The tradeoff is explicit: APT package resolution, including bubblewrap, is not claimed to be bit-for-bit reproducible. The resulting image is instead validated by the complete AMD64 build, runtime smoke tests and Trivy scans before public tags are promoted. This does not add privileges, capabilities or weaker sandbox settings.
Why
The repository previously used mutable GitHub Action tags, a mutable Ubuntu tag and release checksums obtained dynamically during the same build that downloaded the assets. It also had no vulnerability gate for completed or published images.
The first Trivy run proved the value of the new control by detecting
CVE-2026-59873in npm's bundledtar7.5.13. The PR fixes the finding instead of suppressing it. The completed-image scan remains the source of truth for the dependency tree actually shipped.Version policy
check-upstream.yml.Security impact
Validation
Current reviewed head:
ad34dbfef1ed439ec4916c969d36b9bf8344872a.CRITICALvulnerabilities remain in either image.The stable and edge publication workflows are structurally validated in the PR, but their GHCR push-and-promote paths only execute on a stable tag or after merge to
main. The first edge publication after merge remains the final integration test for registry promotion.Scope note
This PR hardens the external image, Action, release-asset and publication boundaries without claiming fully hermetic builds. APT repositories and language runtimes installed through mise remain controlled and tested inputs, but not snapshot-backed bit-for-bit reproducible inputs.