diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 2b6fe6d5..c5624dae 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -46,15 +46,9 @@ jobs: [[ "$tag_commit" =~ ^[0-9a-f]{40}$ ]] git checkout --detach "${tag_commit}" [[ "$(git rev-parse HEAD)" == "$tag_commit" ]] - mkdir -p artifacts - gh release download "$tag" --repo "$GITHUB_REPOSITORY" \ - --pattern image-reference.txt --dir artifacts - image_ref="$(cat artifacts/image-reference.txt)" - [[ "$image_ref" =~ ^ghcr\.io/ratio1/r1-meshdb@sha256:[0-9a-f]{64}$ ]] { printf 'tag=%s\n' "$tag" printf 'tag_commit=%s\n' "$tag_commit" - printf 'image_ref=%s\n' "$image_ref" } >> "$GITHUB_OUTPUT" - name: Verify release source and fixture boundaries @@ -67,6 +61,20 @@ jobs: python3 scripts/generate-source-manifest.py --check scripts/verify-upstream-provenance.sh + - name: Resolve exact released image + id: image + env: + GH_TOKEN: ${{ github.token }} + RELEASE_TAG: ${{ steps.release.outputs.tag }} + run: | + set -euo pipefail + mkdir -p artifacts + gh release download "$RELEASE_TAG" --repo "$GITHUB_REPOSITORY" \ + --pattern image-reference.txt --dir artifacts + image_ref="$(cat artifacts/image-reference.txt)" + [[ "$image_ref" =~ ^ghcr\.io/ratio1/r1-meshdb@sha256:[0-9a-f]{64}$ ]] + printf 'image_ref=%s\n' "$image_ref" >> "$GITHUB_OUTPUT" + - name: Install Cosign uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 with: @@ -75,13 +83,13 @@ jobs: - name: Verify signature, attestations, and anonymous pull env: GH_TOKEN: ${{ github.token }} - run: scripts/verify-image.sh '${{ steps.release.outputs.image_ref }}' '${{ steps.release.outputs.tag }}' + run: scripts/verify-image.sh '${{ steps.image.outputs.image_ref }}' '${{ steps.release.outputs.tag }}' - name: Record raw immutable-image findings uses: aquasecurity/trivy-action@ed142fd0673e97e23eac54620cfb913e5ce36c25 with: version: v0.73.0 - image-ref: ${{ steps.release.outputs.image_ref }} + image-ref: ${{ steps.image.outputs.image_ref }} format: json output: artifacts/trivy-raw.json severity: CRITICAL,HIGH @@ -93,7 +101,7 @@ jobs: TRIVY_VEX: security/openvex.json with: version: v0.73.0 - image-ref: ${{ steps.release.outputs.image_ref }} + image-ref: ${{ steps.image.outputs.image_ref }} format: json output: artifacts/trivy-vex.json severity: CRITICAL,HIGH diff --git a/source/manifest.sha256 b/source/manifest.sha256 index abebc519..35f5fab1 100644 --- a/source/manifest.sha256 +++ b/source/manifest.sha256 @@ -3,7 +3,7 @@ 1e67bf680bc339b93c4587430053354ce2cc63fee29a61cf27c3bc00258fb682 .github/workflows/ci.yml f53d3da2d034b1db8cf6c3d4120c43ec798a5b1b452ca77ecb51576fc994b21d .github/workflows/cloudflare-cleanup.yml 80b25ad118eb48ad5e2be32ab3907af79db693cc65b43c594ad7b441f55cc413 .github/workflows/release.yml -eb7f3d450b8fbf95dba22be5e077277ff7a8f49631e36e8b5e8ac89c49324f95 .github/workflows/security.yml +5f2507148965114df76e05ddecb25ea419400fd9f655d71dd7d13eee226a51bd .github/workflows/security.yml 696452e46b8506219542eb7135c99419725055c59bd15e00e610d567d3a67ac6 .gitignore fe73738d8611a7a6f2c6cfb90c848e2199af7c2bad05e8c40275b8dc8b0efab7 Dockerfile 24f9c32c2d3b165c1f9eb4a8aa2c582412a06b3c0c4630f9c77c4f5a6c3937e5 LICENSE @@ -12140,5 +12140,5 @@ c7bacb9dffc56a0411b55022538de645e5fa8fb18455e397d782366a9d371114 tests/runtime- 8e321ca8065577c96f3dfa35c96deb21771a001c76775ac2ecc7295a316ad2a3 tests/runtime-supervision/tail-test-stub.sh 91b1138b515c45788533118b27f08efd49013e6e9806166580d6e14e2d8c0680 tests/test_cloudflare_cleanup_recovery.py 7be07ef767a2132c79ae431847edce048b935aae4fc5e71fc938005a16460a23 tests/test_cloudflare_ephemeral_tunnels.py -56769694071bd3d58c42392dc54480c2f344a7c348e8e26c9b62fe92f859095a tests/test_release_contract.py +e2924e1348f45c38df1a625b9792346fea1145144dda2a6c337a71458f465e06 tests/test_release_contract.py a52e62e437de00e1504c383419056e96cddf18b15a85e0053f63136184bb7722 tests/test_sbom_contract.py diff --git a/tests/test_release_contract.py b/tests/test_release_contract.py index 6212d108..79c07d83 100755 --- a/tests/test_release_contract.py +++ b/tests/test_release_contract.py @@ -1221,6 +1221,11 @@ def test_scheduled_vex_scan_uses_the_release_revision(self): workflow.index('git checkout --detach "${tag_commit}"'), workflow.index("TRIVY_VEX: security/openvex.json"), ) + self.assertLess( + workflow.index("python3 scripts/generate-source-manifest.py --check"), + workflow.index("gh release download"), + "generated release evidence must not exist during source-manifest verification", + ) def test_runtime_supervision_overlay_is_scratch_compatible(self): dockerfile = read("tests/runtime-supervision/Dockerfile")