Skip to content

fix(supply-chain): pin Dockerfile base images by digest - #216

Closed
seonghobae wants to merge 5 commits into
developfrom
security/pin-docker-base-digests-622e5e6
Closed

fix(supply-chain): pin Dockerfile base images by digest#216
seonghobae wants to merge 5 commits into
developfrom
security/pin-docker-base-digests-622e5e6

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Purpose

Advance #215 / #165 from exact protected develop@622e5e6c3d534f230c390f10e3832efadfc01825 with one bounded container-build input-integrity slice. Protected Dockerfile used mutable tag-only Maven/Temurin base images, so the same protected source could resolve to different upstream bytes without a mightyETL commit.

This remains a direct-develop Draft. It changes only production Dockerfile base-image identity, one focused repository-policy test, source-local supply-chain doctoring and CHANGELOG.md. It does not create a release workflow, alter Compose/.dockerignore, service behavior, Java/Maven version intent, runtime user, entrypoint, credentials, or canonical #149 documentation.

Exact current identity

  • protected/live base: develop@622e5e6c3d534f230c390f10e3832efadfc01825;
  • branch: security/pin-docker-base-digests-622e5e6;
  • production RED source: d94c27578017a030c56547bd4285de3e2ee3436c;
  • behavior GREEN source: f1fd9eec5f6d7eded25cb27ab2ec6a0916577d4b;
  • documentation RED source: 7c1ca42e260c9fe442eb6a1ea7224027ea1a3d7e;
  • exact current GREEN source: 60ca61b36df9e61e7bd2721e165e3959f969d23e;
  • current synthetic merge preview: 884b9c78ea02892a078ecf2cdf6b8b22d192c2f4;
  • Draft / mergeable: true / true;
  • formal reviews: none;
  • unresolved review threads: zero.

Every check/review from a predecessor source head is historical after movement.

RCA

  • Immediate cause: both external FROM instructions used tags without @sha256:.
  • Technical root cause: semantic version intent and immutable image identity were conflated; upstream tag movement could change compiler/runtime/OS bytes without repository change.
  • Control failure: no repository test rejected tag-only external Dockerfile inputs and no source-backed operator/release guidance explained how pinned digests must be reviewed or updated.
  • Release relationship: [Release/Supply chain] Establish reproducible exact-head artifacts and provenance #165 requires container base-image digest/build-context identity for reproducibility/provenance; this PR supplies only the bounded source-side image-input invariant.

RED 1 — hosted production-Dockerfile proof

d94c27578017a030c56547bd4285de3e2ee3436c added only RepositoryDockerBaseImagePolicyTest. It parses every real external root-Dockerfile FROM and requires an explicit readable non-latest tag plus a full lowercase sha256:<64 hex> digest.

CI 31364843626, macOS job 93380916213, checked out synthetic merge 7780796b88e4c96b35d594b6fe0984deb5aaff7f. Production/test compilation was healthy and ETL ran 276 tests with exactly one failure, zero errors/skips: everyExternalDockerBaseImageKeepsReadableTagAndPinsFullSha256Digest, on the tag-only Maven image. This is valid RED at the intended production-Dockerfile boundary, not setup/import/fixture/dependency failure.

GREEN 1 — immutable image input

Immediately before the production mutation, the PR head, protected base, Dockerfile blob and current official Docker Hub tag evidence were re-read. The exact declared tags resolved to the reviewed multi-platform index digests:

  • maven:3.9.13-eclipse-temurin-25sha256:ade3c87e3cdfbe04932afa16b31814cbf60b0122d21d78a76530684a1eeb7cc2;
  • eclipse-temurin:25-jresha256:681c543d6f36c50f45e9b5226930a46203dcfa351d3670e9d0bdf0dabae53539.

f1fd9eec5f6d7eded25cb27ab2ec6a0916577d4b changed only the two FROM lines to tag@sha256:index-digest; Maven/JDK/JRE tag intent, stages, build command, non-root runtime user and entrypoint remained unchanged. Hosted CI 31365172201 then succeeded across macOS/Ubuntu/Windows, including the new Dockerfile test, while full ETL/CDC/gateway suites were green.

RED 2 → GREEN 2 — source-backed update/recovery authority

After behavior GREEN, 7c1ca42e260c9fe442eb6a1ea7224027ea1a3d7e changed only the test contract to require docs/doctoring/docker-base-image-digest-pinning.md plus a discoverable CHANGELOG entry. CI 31365421591, macOS job 93382649010, compiled production/tests successfully and ran ETL 277 tests with exactly one failure, zero errors/skips because the doctoring artifact was absent. The original Dockerfile digest assertion remained green. This is valid documentation RED.

Exact current source 60ca61b36df9e61e7bd2721e165e3959f969d23e now records:

  • mutable-tag versus immutable-digest semantics;
  • explicit readable tag + multi-platform index digest boundary;
  • dated current digest evidence rather than timeless SHA claims;
  • reviewed tag/digest update procedure;
  • rollback/forward-update safety when an older digest would restore a known vulnerability;
  • separation from final image byte reproducibility, SBOM/provenance, licensing, scanner completeness and release readiness;
  • APA 7 primary Docker references;
  • an Unreleased CHANGELOG entry for digest-pinned Docker base images.

Exact-current-head hosted evidence

All exposed workflow aggregates associated with exact source head 60ca61b36df9e61e7bd2721e165e3959f969d23e are terminal-success:

  • CI 31365735134: success on Ubuntu, macOS and Windows;
  • Dependency Review 31365735174: success;
  • CycloneDX SBOM 31365735125: success;
  • SAST Semgrep 31365735194: success;
  • Security Scan 31365735151: aggregate success.

CI macOS job 93383586833 checked out synthetic merge 884b9c78ea02892a078ecf2cdf6b8b22d192c2f4, not literal source head. RepositoryDockerBaseImagePolicyTest passed 2/2; ETL ran 277/277 green, CDC 106/106 green, gateway 3/3 green, and the full reactor completed BUILD SUCCESS.

The same CI log still reports Analyzed bundle 'etl-service' with 0 classes before declaring JaCoCo success. #162/#164 owns selected-class non-vacuity and #205 owns repository-wide production coverage scope. This aggregate is therefore not accepted 100% owned-production coverage evidence.

Hard Trivy job 93383587126 likewise checked out synthetic merge 884b9c78..., not literal source, and printed Dependency version cannot be determined. Child dependencies will not be found. before producing a zero-findings SARIF. #196 owns scanner dependency-graph completeness. It also continues to encounter the tracked 82 MB zipkin.jar, separately owned by #168/#169. Aggregate Security Scan success is therefore not accepted as complete release/merge security evidence.

The current reactor also reproduces a separate platform-dependent Maven resource-encoding warning; issue #217 now owns that reproducibility gap and explicitly defers root-POM mutation while #160 owns the current pom.xml writer lane.

Primary references

Docker. (2026). Building best practices. https://docs.docker.com/build/building/best-practices/

Docker. (2026). Dockerfile reference. https://docs.docker.com/reference/dockerfile/

Docker. (2026). Image digests. https://docs.docker.com/dhi/core-concepts/digests/

Merge boundary

Keep Draft. Digest pinning is one supply-chain input control; it does not establish byte-for-byte final-image reproducibility, release provenance, licensing/NOTICE rights, literal-source acceptance, complete scanner dependency resolution, non-vacuous coverage or independent approval. Merge only when the unchanged exact source head satisfies live repository/CWL policy, accepted literal-source deterministic/security evidence, complete same-revision dependency/SBOM/vulnerability evidence, applicable non-vacuous owned-production coverage, zero valid unresolved findings, qualifying independent non-author formal approval where required, and branch protection/rulesets permit expected-head merge. No predecessor-head, incomplete-scanner, skipped-required, status-only or synthetic-only evidence transfers.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: dad0f894-1906-4ed1-bcb1-fe967e93f24d

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

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.

1 participant