[MAIN-HEALTH-CI-003] Restore Container Security runtime compatibility - #3674
[MAIN-HEALTH-CI-003] Restore Container Security runtime compatibility#3674ootakazuhiko wants to merge 4 commits into
Conversation
❓ Code Generation Drift DetectionStatus: Automated by AE-Framework Codegen |
❓ Code Generation Drift DetectionStatus: Automated by AE-Framework Codegen |
❓ Code Generation Drift DetectionStatus: Automated by AE-Framework Codegen |
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
CodeX Artifacts Summary
|
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
Generate Artifacts PreviewGenerated at: 2026-07-31T03:42:37.742Z
|
AE-Spec Validation ReportStatus: ✅ Passed Validation Results
AE-IR Summary
BDD Step Lint (non-blocking)Usecases: 1 Issues: 1
|
KvOnce Trace Validation
|
There was a problem hiding this comment.
Pull request overview
This PR restores deterministic, fail-closed execution for the Security Analysis → Container Security lane on GitHub-hosted Ubuntu runners by introducing a bounded container runtime preflight contract and wiring it into the workflow so runtime/toolchain incompatibilities are diagnosed (and surfaced) before the repository image build/scan path runs.
Changes:
- Add a new
container-runtime-diagnostic/v1schema + producer (container-runtime-preflight.mjs) to inventory tool/runtime state, enforce digest-pinned smoke checks, and record stable failure classifications. - Update
security.ymlContainer Security job to use the preflight outputs (explicit runtime binding, bounded artifact validation, fail-closed SARIF behavior, artifact upload on success/failure). - Add unit tests + fixtures validating the contract semantics and asserting workflow behavior/ordering.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
.github/workflows/security.yml |
Adds focused workflow_dispatch mode and rewires Container Security to run the runtime preflight, bind runtime paths, validate artifacts, and upload the diagnostic artifact. |
scripts/ci/container-runtime-preflight.mjs |
New preflight/runner that inventories Podman + OCI runtimes, runs minimal smoke/build checks, enforces bounded evidence, and records stage outcomes. |
scripts/ci/lib/container-runtime-diagnostic.mjs |
New shared contract logic: schema constants, sanitization, bounded artifact inspection, and semantic validation helpers. |
schema/container-runtime-diagnostic-v1.schema.json |
New JSON Schema defining the container runtime diagnostic evidence contract. |
fixtures/container-runtime/valid-runc.container-runtime-diagnostic.json |
Adds a reviewed passing fixture for runc selection path (used in schema/semantic validation). |
fixtures/container-runtime/valid-crun.container-runtime-diagnostic.json |
Adds a reviewed passing fixture for crun selection path (used in schema/semantic validation). |
scripts/ci/validate-json.mjs |
Registers the new schema + semantic validator in the JSON validation suite. |
tests/unit/ci/container-runtime-preflight.test.ts |
Adds unit tests covering semantic invariants, bounded sanitization, artifact checks, and timeout behavior. |
tests/unit/ci/container-security-runtime-workflow.test.ts |
Adds workflow contract tests asserting fail-closed semantics, ordering, and runtime binding in security.yml. |
docs/reference/CONTRACT-CATALOG.md |
Documents the new artifact/schema producer/consumer mapping in the contract catalog (EN/JA sections). |
docs/infra/container-runtime.md |
Updates the SSOT runbook with the GitHub-hosted Container Security runtime/preflight model and update procedure. |
docs/ci/ci-troubleshooting-guide.md |
Updates troubleshooting guidance to reflect fail-closed SARIF behavior and the diagnostic artifact. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Issue #3672 verification summaryExact fix head: Runtime correction
Validation
Independent exact-head Container Security runs
Both are attempt 1 at exact head Remaining limitations
|
❓ Code Generation Drift DetectionStatus: Automated by AE-Framework Codegen |
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
❓ Code Generation Drift DetectionStatus: Automated by AE-Framework Codegen |
Cedar Policies (report-only)Files: 1 (json=0, cedar=0) Policy: report-only |
CodeX Artifacts Summary
|
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
Human review response — Container Security evidence contractExact fix commit: The requested evidence-contract hardening is complete on the existing Draft PR:
Validation:
Remaining limitations:
|
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
CodeX Artifacts Summary
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b480412d3
ℹ️ 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".
❓ Code Generation Drift DetectionStatus: Automated by AE-Framework Codegen |
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
CodeX Artifacts Summary
|
Latest runtime-evidence review responseExact fix: The unresolved review finding is addressed and its thread has been replied to individually and resolved.
Validation:
Remaining limitation: both accepted hosted jobs used |
Solo-maintainer merge decision
This supersedes any earlier decision associated with a previous PR head. |
🔍 Verification Summary
Unlinked (top 5)Linked examples (up to 3)Hit basis (tests/formal)- Test hits: title=0 id=0 tag=0 - Formal hits: title=0 id=0 tag=0Non-OK completed modules (top 5)Alloy non-OK completed executions (top 5) |
CodeX Artifacts Summary
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da5e996594
ℹ️ 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".
| if (result.exitCode !== 0 || !version) { | ||
| return { name, path: null, version: null, source: 'unknown', available: false }; | ||
| } |
There was a problem hiding this comment.
Preserve Podman version-probe failures
When an existing Podman executable’s --version probe times out or exits nonzero, this branch discards the observed exit code, duration, timeout state, and executable path; the later missing-Podman branch consequently records a fabricated zero-duration podman-info failure with runtime-unavailable. The fresh evidence beyond the prior runtime-candidate fix is this separate inventory path, which still converts an observed probe failure instead of preserving it in the normalized diagnostic.
AGENTS.md reference: AGENTS.md:L27-L27
Useful? React with 👍 / 👎.
Summary
Implements #3672 under parent program #3655.
Restores a deterministic, fail-closed Security Analysis → Container Security runtime path after the GitHub-hosted Ubuntu runner image transition exposed an OCI runtime incompatibility.
058975117e87b30c223d0b6c0f9eddd12810319bRuntime failure evidence review follow-up (current head)
Exact head: da5e996
Fix commit: da5e996 — fix(ci): preserve runtime preflight failure evidence
The latest review identified that the no-preferred-runtime path fabricated a zero-duration minimal-run failure. The closed replacement now:
Validation: focused runtime/workflow matrix 91/91; full unit 213 files with 1443 pass and 1 skipped; types, build, API snapshot, 101-schema validation, fixture validation, docs consistency, Verify Lite, actionlint 1.7.12, Context Pack, Boundary Map, and diff check all pass.
Exact-head CI: Verify Lite 30598414851, Policy Gate 30598414871, Copilot Review Gate 30598943455, coverage 30598414951, Security 30598415058, Quality Gates 30598415127, and Full CI 30598415323 succeeded.
New independent focused acceptance:
Compatibility impact is limited to the unmerged Draft evidence contract: success artifacts are unchanged, while synthetic or candidate-mismatched failure summaries are now rejected. Existing check names, security thresholds, and runtime selection remain unchanged. Rollback this review fix by reverting da5e996; the earlier evidence hardening rollback remains 2b48041.
Evidence-contract hardening follow-up (prior head 2b48041)
Human review of the prior head identified four contract-hardening themes plus an explicit completion boundary. Commit
2b480412d329888917b62c7d9b8c0226d142f05faddresses them without changing the repaired runtime selection:/paths, rejects./../ backslashes / absolute paths, walks every component withlstat, rejects final and intermediate symlinks (including links back into the repository), and rechecks canonical parent/file containment. This is bounded pre-read validation, not an atomic-open claim.oversized-output/sarif-malformed.manifest-detect -> repository-build -> image-user -> archive-export -> trivy-pull -> trivy-scan -> sarif-validate -> sarif-upload.archive-export=passis rejected whenimage-useris absent,not-run, or failed.pass,fail, andnot-runhave closed exit-code/detail/classification rules; unavailable candidates cannot pass and selected candidates must be available. Timeout, missing, malformed, and oversized states are not converted.pipelineComplete=false. A newfinalizecommand requires all 12 reviewed check IDs exactly once and allpass, runs after recorded SARIF upload success, and is the only path topipelineComplete=true. The diagnostic artifact is uploaded after finalization on success and remains uploadable withfalseon failure.Follow-up validation completed locally: 83/83 focused contract/workflow tests; Schema and fixture validation; types, build, API snapshot, docs consistency, Verify Lite; actionlint 1.7.12; Context Pack and Boundary Map; and
git diff --check. Local Podman 4.9.3 / crun 1.14.1 completed preflight, production build, non-root inspection, 1.31 GiB archive export, Trivy 0.72.0 scan, and SARIF validation. Local evidence correctly remainspipelineComplete=falsebecause GitHub SARIF upload is not available locally.Compatibility: the
pipelineCompletefield is required by the current Draft contract. Artifacts from the superseded Draft head are intentionally not accepted as final evidence by this head; no releasedmaincontract or required check name is changed. Rollback is the single follow-up commit2b480412.Source evidence and root cause
90809008864ubuntu-24.04 / 20260726.254.1RUNfailed through/usr/bin/crun:unknown version specified9095100369920260726.254.1/ eastus2RUNOCI-runtime startup failure9095217391520260726.254.1/ eastusRUNOCI-runtime startup failure9085189722420260720.247.2/ centralusAll four source runs pulled the same observed
node:22-alpineconfig digestsha256:395425e54d98ebbd748d388685a0c2de151a30fa92fffc10ba30fa63f3db64d6; mutable application-base content was not the observed differentiator.The
20260726.254hosted image release changed the runner-provided Podman bundle from 4.9.3 to 5.8.4. The former workflow then installed Ubuntu Podman 4.9.3 and its configuration/runtime tuple at job time. This created a mixed hosted-bundle/Ubuntu-package state that selected/usr/bin/crun1.14.1 and failed before the repository command could start. The failure reproduced on three regions and was therefore not classified as a single-run transient.Chosen remediation
Issue option 1: retain the hosted image's reviewed container surface without job-time package mutation, then select only a runtime that passes the closed preflight.
apt-get install podmanfeaturesplus minimalpodman runfor every available crun/runc candidate/usr/local/bin/runcwhen present, otherwise permit the reviewed/usr/bin/runcfallback only after the same direct and minimal smoke checkspodman info --debugto report the same effective runtimeRUN truebuild before the repository buildcontainer-runtime-diagnostic/v1on success or failureNo PPA, unsigned binary, alternate builder, self-hosted runner, warning conversion, threshold change, or security-lane skip was introduced.
Closed diagnostic contract
New contract surfaces:
schema/container-runtime-diagnostic-v1.schema.jsonscripts/ci/container-runtime-preflight.mjsscripts/ci/lib/container-runtime-diagnostic.mjsStable classifications include
runtime-ready,manifest-missing,runtime-missing,runtime-version-incompatible,runtime-selection-invalid,minimal-run-failed,minimal-build-failed,repository-build-failed,archive-export-failed,scan-failed,sarif-missing,sarif-malformed, andsarif-upload-failed.Stage prerequisites are checked before external execution. Report/artifact paths are repository-bound, canonical, regular and non-symlink where applicable. Command execution is shell-free, time-bounded, and output-bounded. Environment dumps, tokens, private graph-root paths, and raw unbounded output are not retained. The newly controlled Alpine smoke and Trivy images are tag+digest pinned.
Normal and focused event semantics
Normal push/schedule behavior remains enforced and cannot silently skip Container Security.
workflow_dispatch mode=container-securityis a focused diagnostic surface. It requiresexpected_headto be a lowercase 40-character SHA equal togithub.sha. It runs Container Security while deliberately skipping unrelated heavy security lanes; focused success is not represented as a complete Security Analysis or #3671 dependency result. Scheduled security notification now waits for Container Security as well.Prior reviewed-head runtime evidence (superseded for final acceptance)
These runs were independent attempt-1 workflow dispatches on superseded head
d75a4853f2f7c6e863118330708eddb0b59f5e50. They remain runtime-repair evidence, but they do not satisfy the hardenedpipelineCompletecontract on the current head.20260720.247.2/ northcentralus20260720.247.2/ westus24.9.3/1.33.7/2.1.10/usr/bin/crun1.14.1/usr/bin/runc1.3.6nextjsinspectionruntime-readyruntime-readyDiagnostic artifact SHA-256 values are
a154f27a1a86e5f0c044301f15780c346afcb38265cab4acf89df89cfb6771deand02ae66794141b6fb038a77127671aeca1da6280fb1d6fa229b937b35092eecfc; the bytes differ only in observation-specific fields such as timestamp/duration, while both closed semantic check sets contain 12 passes and zero failures.Local validation
Completed on repository-pinned pnpm 10.0.0:
pnpm -s run types:checkpnpm -s run buildpnpm -s run api:checkpnpm -s run check:schemaspnpm -s run check:doc-consistencypnpm -s run verify:litegit diff --checkThe repository has no
pnpm checkcommand; it exits 254 because no such script exists. Its constituent checks were run explicitly.Acceptance
continue-on-error,|| true, warning conversion, permission expansion, or threshold relaxation was addedpipelineComplete=truePrior reviewed-head CI and authority (superseded)
main@c5da6115638fdbfeebbc458b39fa6916db66afb0d75a4853f2f7c6e863118330708eddb0b59f5e50sha256:6856b0c1c45d319580ea4fc81f7023299125d3361ee91824680173c4a671c2f0Prior evidence-contract exact-head acceptance (superseded by da5e996)
2b480412d329888917b62c7d9b8c0226d142f05fpipelineComplete=true, 12/12 checks pass, hashes3a27c9689b5cb43c76c8a6d3ccfb5d46a2eb09eb25a7437d1485c5ee6b98e098andcd1fc0bfff55c47f65474c156321fa21d7a822612f7a92e437492dbc93f3cec9ubuntu24 / 20260720.247.2, Podman 4.9.3, selected/usr/bin/runc1.3.6. GitHub did not allocate20260726.254.1; no allocation is inferred.Trust, compatibility and rollback
contents: read,actions: read,security-events: write.persist-credentials: false.pipelineCompleteis now required and previous Draft-head artifacts are not final evidence. Existing required check names are unchanged.2b480412; full runtime repair rollback remainsd75a4853, thenf17e8094.Rejected alternatives
node:22-alpine: not included because the same config digest was observed in success and failure; broad image freshness policy is outside [MAIN-HEALTH-CI-003] Restore Container Security after Podman/crun runtime incompatibility #3672.Remaining limitations
The two exact-head acceptance runs were scheduled on the currently served
20260720.247.2image, not the failing20260726.254.1image. The preflight supports the reviewed/usr/local/bin/runc1.4.3 bundle on the latter image, but GitHub did not schedule that image during acceptance; this external image-allocation fact is retained rather than inferred away.The diagnostic
sourcevalue is a bounded path class (/usr/localrunner bundle vs/usrsystem package path), not cryptographic package-ownership provenance. Content-addressed binary provenance is not claimed.The repository production base image remains tag-based; this PR intentionally does not broaden into unrelated image-pinning policy.
[MAIN-HEALTH-SEC-002] Eliminate current high dependency vulnerabilities and restore enforced security gates #3671 dependency findings remain a separate baseline until PR [MAIN-HEALTH-SEC-002] Restore dependency security gates #3673 is completed; focused [MAIN-HEALTH-CI-003] Restore Container Security after Podman/crun runtime incompatibility #3672 runs skip that lane and do not reinterpret it as Container Security evidence.
Artifact validation is a non-atomic pre-read check. Concurrent filesystem mutation and hard-link inode provenance are not claimed; the workflow-controlled artifact directory and exact-head job boundary remain the current mitigation.
Human decisions required
None. If later hosted images cannot supply any runtime that passes direct, minimal and repository execution, the workflow fails closed and the builder/runner migration decision returns to the bounded human-decision boundary in #3672.