Digest-pin every Dockerfile base image

Task 11149 · Done · Coder · created · updated

Epic: Security audit of development keys and container artifacts. This child = Architecture C8 (PRD R6). ## Original requirement (verbatim, epic body) - "The installers run `curl | sh` with no checksum or signature. Images are tag-pinned with a `:latest` fallback, not pinned by digest, and not cosign-signed. Base images are unpinned." - "3. Sign the images and pin them by digest, and have the installers check a checksum." - "It should not break anything in prod or dev" Operator decision D3: all base images (CE and `infra/local`) are digest-pinned with Dependabot bumps. This child owns base images only; signing and the compose pins are a sibling child. ## Approach (Architecture C8) - Every `FROM` in `infra/community-edition/Dockerfile.*` and `infra/local/Dockerfile.*` becomes `image:tag@sha256:<index digest>`. - Use the multi-arch index digest: the top-level `Digest` from `docker buildx imagetools inspect <image:tag>`. Never a platform digest, because api and web also build arm64. - Keep the tag for readability. - `infra/local/Dockerfile.jaahd-test`: `ARG UBUNTU_VERSION=26.04` stays the single home that `tools/jaahd_container_suite.sh:64-65` checks. - Add `ARG UBUNTU_DIGEST=sha256:…` and `FROM ubuntu:${UBUNTU_VERSION}@${UBUNTU_DIGEST}`, with a comment to bump it together with `UBUNTU_VERSION`. - `cgr.dev/chainguard/wolfi-base`: pin as `:latest@sha256:…`. The free tier publishes only `latest`. - Dependabot already covers both directories (`.github/dependabot.yml:93,108`). Cite it; do not edit it. ## PRD R6 — Pin all base images by digest (A4; D3) — verbatim - AC6.1 Every `FROM` in `infra/community-edition/Dockerfile.*` and `infra/local/Dockerfile.*` names `@sha256:` (tag kept for readability); none uses `:latest` alone. - AC6.2 Dependabot (or the repo's existing bump mechanism) proposes digest bumps for these files. - AC6.3 Dev/prod images still build and deploy. Credentials & reach: - Docker Hub / cgr.dev digest lookup (C8, C9) | Anonymous registry reads | verified — `docker buildx imagetools inspect` returned an index digest from h2 for `postgres:18`, `cgr.dev/chainguard/wolfi-base:latest`, `node:26-alpine` - arm64 image builds for digest-pin oracle (C8) | buildx with arm64 emulation | verified — `docker buildx ls` on h2 lists a running builder with `linux/arm64` - Quick/full gate, pytest, CE tree build + `check_tree`, installer harness, tree console build | Worktree only (`./dc`, `tools/community_edition/*.py` present) | verified — files present on h2; no credential needed - PR checks / merge lane / Jaah Deploy run status | `jaah-forge` (pre-authenticated for the task) | verified — read verb `pr list` succeeded from h2 - Dev console boots, sign-in, Slack/Telegram settings, attachment upload (AC2.3, AC4.5, AC9.2) | `org/console/dev-login` (credential_get succeeded); environment: dev control plane | **deferred** to a node with reach. dev timed out from h2 (prod `app.jaah.ai` answered 200). Operator answer A5: a green Jaah Deploy is the gate, and the browser check runs on a node that reaches dev; a builder without reach records it deferred Out of scope: PRD §5, verbatim: - Do NOT change `infra/community-edition/node/install_clis.sh`'s vendor `curl https://claude.ai/install.sh | bash` (D8; deferred follow-up). - Do NOT sign or digest-pin the cloud deploy images pushed by Jaah Deploy, nor add deploy-time verification (D3 chose CE + base images only). - Do NOT add a CI/terraform guard over ECS env (D7 verify-only). - Do NOT cosign-sign `SHA256SUMS` (D4). - Do NOT remove Slack, Telegram, headscale, AWS, KMS, S3 or Bedrock from the cloud edition — the prune is CE-tree only. - Do NOT change the session-secret / dev-seed / insecure-agent refusals' semantics or the `FIXTURE_APP_ENVS` set. - Do NOT touch `infra/jaah/terraform` resources (only read them for R2). - Do NOT change port binds, setup-loopback rule, cookie flags or rate limits (A6 positives). - Architecture boundary: do not edit `infra/community-edition/compose.yml` or the release workflow (sibling child); do not edit `.github/dependabot.yml`; no base-image version bumps — pin the tag already in use. Done means: - AC6.1 — `grep -hn "^FROM" infra/community-edition/Dockerfile.* infra/local/Dockerfile.* | grep -v "@sha256:"` prints nothing (the ARG-parametrised ubuntu line resolves to a digest-pinned value); each pinned digest is a multi-arch index (`docker buildx imagetools inspect` shows a manifest list/index) — cite it per image. - AC6.2 — the report cites `.github/dependabot.yml` docker entries covering both directories. - AC6.3 — `./dc up` builds locally; the CE images build from the tree for linux/amd64 and linux/arm64 (`docker buildx build --platform linux/amd64,linux/arm64 -f infra/community-edition/Dockerfile.{api,web,node}` in the built tree); the PR's Jaah Deploy succeeds. - AC9.1 `./dc check quick` green on the branch; merge lane `./dc check full` green. - AC9.2 The PR's Jaah Deploy succeeds to dev; dev console loads and a user can sign in. (browser part deferred — dev unreachable from h2; operator A5: green Jaah Deploy is the gate)

Outcome

Digest-pinned every base-image FROM in infra/community-edition and infra/local (multi-arch index digests; ubuntu via ARG UBUNTU_DIGEST). Local and amd64+arm64 CE builds green; lane merged #7286 as ffbdc0350. Deploy superseded. Deferred: ubuntu digest bumped by hand. Memory: none applied.

Pull request

Artifacts

Activity

  • Draft
  • Ready
  • Runner started
  • Runner ended (done)