From 6612f09628f0695c2a5f2937d2b853cbe1a1d81c Mon Sep 17 00:00:00 2001 From: Omar Ibrahim <31526072+omar07ibrahim@users.noreply.github.com> Date: Sun, 9 Aug 2026 12:43:41 +0000 Subject: [PATCH 1/5] Harden generated artifact permissions --- README.md | 2 +- SECURITY.md | 4 ++++ tests/test_evidence.py | 15 +++++++++++++++ tests/test_pack_evidence.py | 1 + tools/generate_evidence.py | 2 +- tools/generate_pack_evidence.py | 1 + 6 files changed, 23 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3c7c2a7..9696591 100644 --- a/README.md +++ b/README.md @@ -107,7 +107,7 @@ tools/capture_pack_report.sh python3 -W error -m unittest discover -s tests -v ``` -Current verified baseline: **89 tests**, **9/9 graph invariants**, **7/7 pack/index checks**, **57 isolated Git invocations** in the DAG evidence run, two independently replayed evidence packages, and two attested offline browser captures. +Current verified baseline: **90 tests**, **9/9 graph invariants**, **7/7 pack/index checks**, **57 isolated Git invocations** in the DAG evidence run, two independently replayed evidence packages, and two attested offline browser captures. | Artifact | What it proves | |---|---| diff --git a/SECURITY.md b/SECURITY.md index 37c677e..c7474f8 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -13,6 +13,10 @@ The command boundary is deliberately narrow: - temporary roots with symlinked path components are rejected. - stdout and stderr are captured in private temporary files and rejected before loading into memory when either exceeds 1 MiB. +## Evidence file permissions + +Evidence refreshes reject symlinked targets and multi-link files, stage each generated artifact as owner-read/write only (`0600`), fsync it, and atomically replace the managed target. Committed evidence is intentionally public synthetic data and may be checked out with ordinary repository permissions; this pipeline must not be used for secrets or private inputs. + ## Pack/index closed subset The pack experiment passes only three fixed synthetic blob IDs to `git pack-objects`; it does not accept a repository path, revision, ref, or caller-provided object list. Generated `.pack` and `.idx` files must be regular, single-link files no larger than 1 MiB and must remain the same inode and size across the bounded read. diff --git a/tests/test_evidence.py b/tests/test_evidence.py index 7b1c48e..d18dcc6 100644 --- a/tests/test_evidence.py +++ b/tests/test_evidence.py @@ -5,8 +5,11 @@ import json from pathlib import Path import re +import stat import struct +import tempfile import unittest +from unittest.mock import patch import zlib from tools import generate_evidence @@ -247,5 +250,17 @@ def test_readme_baseline_matches_current_evidence(self) -> None: self.assertIn("11 local subcommands are allow-listed", readme) + def test_writer_keeps_generated_files_owner_only(self) -> None: + with tempfile.TemporaryDirectory() as temporary_root: + root = Path(temporary_root) + with patch.object(generate_evidence, "ROOT", root): + generate_evidence._write_artifacts( + {Path("nested/evidence.txt"): b"public synthetic evidence\n"} + ) + target = root / "nested/evidence.txt" + self.assertEqual(target.read_bytes(), b"public synthetic evidence\n") + self.assertEqual(stat.S_IMODE(target.stat().st_mode), 0o600) + + if __name__ == "__main__": unittest.main() diff --git a/tests/test_pack_evidence.py b/tests/test_pack_evidence.py index ccb03e7..591b217 100644 --- a/tests/test_pack_evidence.py +++ b/tests/test_pack_evidence.py @@ -87,6 +87,7 @@ def test_manifest_binds_artifacts_capture_and_sources(self) -> None: { "git_dag_lab/pack.py", "git_dag_lab/cli.py", + "tools/generate_evidence.py", "tools/generate_pack_evidence.py", "tools/capture_pack_report.sh", }, diff --git a/tools/generate_evidence.py b/tools/generate_evidence.py index a550731..fdd4775 100755 --- a/tools/generate_evidence.py +++ b/tools/generate_evidence.py @@ -1011,7 +1011,7 @@ def _write_artifacts(generated: Mapping[Path, bytes]) -> None: temporary.flush() os.fsync(temporary.fileno()) temporary_path = Path(temporary.name) - os.chmod(temporary_path, 0o644) + os.chmod(temporary_path, 0o600) os.replace(temporary_path, target) temporary_path = None finally: diff --git a/tools/generate_pack_evidence.py b/tools/generate_pack_evidence.py index ac669e2..ff5cb60 100755 --- a/tools/generate_pack_evidence.py +++ b/tools/generate_pack_evidence.py @@ -809,6 +809,7 @@ def build_artifacts(*, allow_missing_screenshot: bool) -> dict[Path, bytes]: "sources": [ _source_row(Path("git_dag_lab/pack.py")), _source_row(Path("git_dag_lab/cli.py")), + _source_row(Path("tools/generate_evidence.py")), _source_row(Path("tools/generate_pack_evidence.py")), _source_row(Path("tools/capture_pack_report.sh")), ], From 71893405604273c590ef5a6faaae46e39578f51e Mon Sep 17 00:00:00 2001 From: Omar Ibrahim <31526072+omar07ibrahim@users.noreply.github.com> Date: Sun, 9 Aug 2026 12:44:36 +0000 Subject: [PATCH 2/5] Stage permission-hardened evidence read-only --- .../workflows/stage-permission-evidence.yml | 92 +++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 .github/workflows/stage-permission-evidence.yml diff --git a/.github/workflows/stage-permission-evidence.yml b/.github/workflows/stage-permission-evidence.yml new file mode 100644 index 0000000..d8bbb57 --- /dev/null +++ b/.github/workflows/stage-permission-evidence.yml @@ -0,0 +1,92 @@ +name: Stage permission-hardened evidence (temporary) + +on: + push: + branches: + - agent/harden-evidence-permissions + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: stage-evidence-permissions-${{ github.ref }} + cancel-in-progress: false + +env: + PYTHONDONTWRITEBYTECODE: "1" + PYTHONNOUSERSITE: "1" + PYTHONHASHSEED: "0" + TZ: UTC + +jobs: + stage: + name: Generate read-only pack evidence artifact + runs-on: ubuntu-24.04 + timeout-minutes: 20 + steps: + - name: Check out the exact feature revision + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + fetch-depth: 1 + persist-credentials: false + ref: ${{ github.sha }} + + - name: Set up exact Python + uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 + with: + python-version: "3.12.12" + + - name: Assert the bounded staging context + shell: bash + run: | + set -euo pipefail + test "$GITHUB_REPOSITORY" = "omar07ibrahim/hello-git" + case "$GITHUB_EVENT_NAME" in + push|workflow_dispatch) ;; + *) exit 1 ;; + esac + test "$GITHUB_REF" = "refs/heads/agent/harden-evidence-permissions" + test "$(git rev-parse HEAD)" = "$GITHUB_SHA" + test "$(python -c 'import platform; print(platform.python_version())')" = "3.12.12" + test -z "${OPENAI_API_KEY:-}" + test "$(git status --porcelain=v1 --untracked-files=normal --ignore-submodules=none)" = "" + + - name: Acquire the digest-pinned browser image + shell: bash + run: | + set -euo pipefail + image='mcr.microsoft.com/playwright@sha256:2f29369043d81d6d69a815ceb80760f55e85f5020371ad06a4d996f18503ad1c' + docker pull "$image" + test "$(docker image inspect --format '{{index .RepoDigests 0}}' "$image")" = "$image" + + - name: Generate and independently replay both evidence packages + shell: bash + run: | + set -euo pipefail + tools/capture_pack_report.sh + python -B tools/generate_evidence.py --write + python -B tools/generate_evidence.py --check + python -B tools/generate_pack_evidence.py --check + python -W error -m unittest discover -s tests -v + bash -n tools/capture_pack_report.sh + test "$(shellcheck --version | awk '$1 == "version:" {print $2}')" = "0.9.0" + shellcheck tools/capture_pack_report.sh + + - name: Upload generated evidence without repository write access + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + with: + name: git-evidence-permission-hardening-${{ github.sha }} + path: | + docs/assets/git-pack-cli.svg + docs/assets/git-pack-fanout.svg + docs/assets/git-pack-integrity.svg + docs/assets/git-pack-layout.svg + docs/assets/git-pack-report.png + docs/demo/git-dag-v1/manifest.json + docs/demo/git-pack-index-v1/ + evidence/git-pack-index-v1.json + if-no-files-found: error + include-hidden-files: false + compression-level: 0 + retention-days: 1 From 57b5b551c6dd9ae37d35d2f9984d93d683a5165a Mon Sep 17 00:00:00 2001 From: Omar Ibrahim <31526072+omar07ibrahim@users.noreply.github.com> Date: Sun, 9 Aug 2026 12:48:44 +0000 Subject: [PATCH 3/5] Harden browser evidence output permissions --- .github/workflows/stage-permission-evidence.yml | 13 ++++++++++--- tests/test_evidence.py | 8 ++++++++ tests/test_pack_evidence.py | 7 +++++++ tools/capture_pack_report.sh | 6 +++--- tools/capture_report.sh | 6 +++--- 5 files changed, 31 insertions(+), 9 deletions(-) diff --git a/.github/workflows/stage-permission-evidence.yml b/.github/workflows/stage-permission-evidence.yml index d8bbb57..1b588de 100644 --- a/.github/workflows/stage-permission-evidence.yml +++ b/.github/workflows/stage-permission-evidence.yml @@ -64,27 +64,34 @@ jobs: shell: bash run: | set -euo pipefail + tools/capture_report.sh tools/capture_pack_report.sh python -B tools/generate_evidence.py --write python -B tools/generate_evidence.py --check python -B tools/generate_pack_evidence.py --check python -W error -m unittest discover -s tests -v - bash -n tools/capture_pack_report.sh + bash -n tools/capture_report.sh tools/capture_pack_report.sh test "$(shellcheck --version | awk '$1 == "version:" {print $2}')" = "0.9.0" - shellcheck tools/capture_pack_report.sh + shellcheck tools/capture_report.sh tools/capture_pack_report.sh - name: Upload generated evidence without repository write access uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: git-evidence-permission-hardening-${{ github.sha }} path: | + docs/assets/evidence-pipeline.svg + docs/assets/git-dag-cli.svg + docs/assets/git-dag-report.png + docs/assets/git-dag-topology.svg + docs/assets/git-object-envelope.svg docs/assets/git-pack-cli.svg docs/assets/git-pack-fanout.svg docs/assets/git-pack-integrity.svg docs/assets/git-pack-layout.svg docs/assets/git-pack-report.png - docs/demo/git-dag-v1/manifest.json + docs/demo/git-dag-v1/ docs/demo/git-pack-index-v1/ + evidence/git-dag-v1.json evidence/git-pack-index-v1.json if-no-files-found: error include-hidden-files: false diff --git a/tests/test_evidence.py b/tests/test_evidence.py index d18dcc6..ba092f6 100644 --- a/tests/test_evidence.py +++ b/tests/test_evidence.py @@ -163,6 +163,14 @@ def test_capture_toolchain_is_digest_pinned(self) -> None: self.assertRegex(capture["browser_sha256"], r"^[0-9a-f]{64}$") self.assertEqual(capture["network"], "none") self.assertEqual(capture["viewport"], {"height": 1800, "width": 1440}) + script = (ROOT / "tools/capture_report.sh").read_text() + self.assertIn( + 'chmod 0600 "$temporary_root/output/git-dag-report.png"', + script, + ) + self.assertIn('chmod 0600 "$dom_path"', script) + self.assertIn("os.chmod(temporary_path, 0o600)", script) + self.assertNotIn("chmod 0644", script) def test_sources_are_hashed_and_path_relative(self) -> None: for source in self.manifest["sources"]: diff --git a/tests/test_pack_evidence.py b/tests/test_pack_evidence.py index 591b217..719b42a 100644 --- a/tests/test_pack_evidence.py +++ b/tests/test_pack_evidence.py @@ -230,6 +230,13 @@ def test_capture_toolchain_is_digest_pinned_and_network_disabled(self) -> None: self.assertIn("--network none", script) self.assertIn("--pull=never", script) self.assertIn("--read-only", script) + self.assertIn( + 'chmod 0600 "$temporary_root/output/git-pack-report.png"', + script, + ) + self.assertIn('chmod 0600 "$dom_path"', script) + self.assertIn("os.chmod(temporary_path, 0o600)", script) + self.assertNotIn("chmod 0644", script) self.assertNotRegex(script, re.compile(r"(?m)^\s*curl\b|\bwget\b")) diff --git a/tools/capture_pack_report.sh b/tools/capture_pack_report.sh index 9b09f7c..4fca50d 100755 --- a/tools/capture_pack_report.sh +++ b/tools/capture_pack_report.sh @@ -221,8 +221,8 @@ if [[ $(sha256sum "$repo_root/tools/capture_pack_report.sh" | awk '{print $1}') exit 1 fi -chmod 0644 "$temporary_root/output/git-pack-report.png" -chmod 0644 "$dom_path" +chmod 0600 "$temporary_root/output/git-pack-report.png" +chmod 0600 "$dom_path" mv -f -- "$temporary_root/output/git-pack-report.png" "$output_path" mv -f -- "$dom_path" "$rendered_dom_path" @@ -312,7 +312,7 @@ try: temporary.flush() os.fsync(temporary.fileno()) temporary_path = Path(temporary.name) - os.chmod(temporary_path, 0o644) + os.chmod(temporary_path, 0o600) os.replace(temporary_path, attestation_path) temporary_path = None finally: diff --git a/tools/capture_report.sh b/tools/capture_report.sh index 21357d9..a61b542 100755 --- a/tools/capture_report.sh +++ b/tools/capture_report.sh @@ -221,8 +221,8 @@ if [[ $(sha256sum "$repo_root/tools/capture_report.sh" | awk '{print $1}') != "$ exit 1 fi -chmod 0644 "$temporary_root/output/git-dag-report.png" -chmod 0644 "$dom_path" +chmod 0600 "$temporary_root/output/git-dag-report.png" +chmod 0600 "$dom_path" mv -f -- "$temporary_root/output/git-dag-report.png" "$output_path" mv -f -- "$dom_path" "$rendered_dom_path" @@ -312,7 +312,7 @@ try: temporary.flush() os.fsync(temporary.fileno()) temporary_path = Path(temporary.name) - os.chmod(temporary_path, 0o644) + os.chmod(temporary_path, 0o600) os.replace(temporary_path, attestation_path) temporary_path = None finally: From e6bc5b24d3d7e8094ee7115def46053749f07bfc Mon Sep 17 00:00:00 2001 From: Omar Ibrahim <31526072+omar07ibrahim@users.noreply.github.com> Date: Sun, 9 Aug 2026 12:53:40 +0000 Subject: [PATCH 4/5] Refresh permission-bound evidence provenance --- docs/assets/evidence-pipeline.svg | 2 +- docs/demo/git-dag-v1/capture-attestation.json | 4 ++-- docs/demo/git-dag-v1/manifest.json | 10 +++++----- .../git-pack-index-v1/capture-attestation.json | 4 ++-- docs/demo/git-pack-index-v1/manifest.json | 15 ++++++++++----- 5 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/assets/evidence-pipeline.svg b/docs/assets/evidence-pipeline.svg index 248cfda..227df9f 100644 --- a/docs/assets/evidence-pipeline.svg +++ b/docs/assets/evidence-pipeline.svg @@ -1,7 +1,7 @@ Reproducible evidence pipeline The actual path from fixed fixture bytes through isolated Git plumbing and independent checks into the checked-in evidence artifacts. - {"capture_attestation":"docs/demo/git-dag-v1/capture-attestation.json","capture_attestation_receipt_sha256":"7c9b58040ada09b40dc57e21c36767d044ec08e8e6a1c928e7dd5da0941ff238","capture_status":"attested","container_image":"mcr.microsoft.com/playwright@sha256:2f29369043d81d6d69a815ceb80760f55e85f5020371ad06a4d996f18503ad1c","network":"none","report_receipt_sha256":"2da1ccd8799699ade939f3901566e448baeb9691973624452231b35594469c84","screenshot_sha256":"e539db1152e8b1d66ee543d045739851991deb2e1a45174eb4358621efd4e17e","source":"evidence/git-dag-v1.json"} + {"capture_attestation":"docs/demo/git-dag-v1/capture-attestation.json","capture_attestation_receipt_sha256":"6e1199b957e5e7cdaf0af582d1547ac5a63137b3a0a3b9eadcb85673e09576b5","capture_status":"attested","container_image":"mcr.microsoft.com/playwright@sha256:2f29369043d81d6d69a815ceb80760f55e85f5020371ad06a4d996f18503ad1c","network":"none","report_receipt_sha256":"2da1ccd8799699ade939f3901566e448baeb9691973624452231b35594469c84","screenshot_sha256":"e539db1152e8b1d66ee543d045739851991deb2e1a45174eb4358621efd4e17e","source":"evidence/git-dag-v1.json"} diff --git a/docs/demo/git-dag-v1/capture-attestation.json b/docs/demo/git-dag-v1/capture-attestation.json index 3a46836..2594024 100644 --- a/docs/demo/git-dag-v1/capture-attestation.json +++ b/docs/demo/git-dag-v1/capture-attestation.json @@ -43,7 +43,7 @@ "schema_version": "git-dag-browser-capture-attestation/v1", "script": { "path": "tools/capture_report.sh", - "sha256": "74dcf776035069299067544d3bd7b8a1443724f1bd7b842876ea53831b0d8441", + "sha256": "124a296ccf38d36a5220c62ea4730fbba2b21414e26b668ded42d855a691d6d5", "size": 10937 }, "viewport": { @@ -55,6 +55,6 @@ "receipt": { "algorithm": "sha256", "canonicalization": "UTF-8 JSON; sorted keys; compact separators", - "sha256": "7c9b58040ada09b40dc57e21c36767d044ec08e8e6a1c928e7dd5da0941ff238" + "sha256": "6e1199b957e5e7cdaf0af582d1547ac5a63137b3a0a3b9eadcb85673e09576b5" } } diff --git a/docs/demo/git-dag-v1/manifest.json b/docs/demo/git-dag-v1/manifest.json index f9504a6..d8492cf 100644 --- a/docs/demo/git-dag-v1/manifest.json +++ b/docs/demo/git-dag-v1/manifest.json @@ -3,7 +3,7 @@ { "path": "docs/assets/evidence-pipeline.svg", "role": "evidence pipeline derived from execution summary", - "sha256": "55504a79c5025689c167020db503ddaf64adb1542776254d5dedb2fa11f8b157", + "sha256": "c20efa2ff42ce32a205d9c83343abae9b43c94826c5a19042b2d2a188b707fe3", "size": 4600 }, { @@ -33,7 +33,7 @@ { "path": "docs/demo/git-dag-v1/capture-attestation.json", "role": "capture provenance binding browser, isolation, input, and outputs", - "sha256": "ea18a02969796afd0900dc5883ab29490bb517bf0f8d74f7f5f6043cb36a7f08", + "sha256": "2df440c8071e0b4ab839527176660ce832acb97b0634915bcf2d795c074a737f", "size": 1990 }, { @@ -69,7 +69,7 @@ ], "capture": { "attestation": "docs/demo/git-dag-v1/capture-attestation.json", - "attestation_receipt_sha256": "7c9b58040ada09b40dc57e21c36767d044ec08e8e6a1c928e7dd5da0941ff238", + "attestation_receipt_sha256": "6e1199b957e5e7cdaf0af582d1547ac5a63137b3a0a3b9eadcb85673e09576b5", "browser_binary": "/ms-playwright/chromium_headless_shell-1193/chrome-linux/headless_shell", "browser_sha256": "003728e0b77eb9d52e4d258594bd55ce22ecd245eb6d3b6858fbd844c901ad7d", "browser_version": "Chromium 140.0.7339.186", @@ -140,12 +140,12 @@ }, { "path": "tools/generate_evidence.py", - "sha256": "442346818e239a4ab9b4fa9804929e61bf266dc7145a543fb40076298d47ce6b", + "sha256": "9276b529ec13eaa6ceda1cab1282b6679a689697e5c6930ca17b5e0bc8ba3a92", "size": 49590 }, { "path": "tools/capture_report.sh", - "sha256": "74dcf776035069299067544d3bd7b8a1443724f1bd7b842876ea53831b0d8441", + "sha256": "124a296ccf38d36a5220c62ea4730fbba2b21414e26b668ded42d855a691d6d5", "size": 10937 } ] diff --git a/docs/demo/git-pack-index-v1/capture-attestation.json b/docs/demo/git-pack-index-v1/capture-attestation.json index cbbb156..cdc139a 100644 --- a/docs/demo/git-pack-index-v1/capture-attestation.json +++ b/docs/demo/git-pack-index-v1/capture-attestation.json @@ -43,7 +43,7 @@ "schema_version": "git-pack-browser-capture-attestation/v1", "script": { "path": "tools/capture_pack_report.sh", - "sha256": "3477eeec4a10026fe95b87803f68657069c77f2b491bd69d3cddd56777924f0b", + "sha256": "7cddc4ec1ba66e203195d9a9eb3c454fe39b3790472106bad410cfc9d313ce8f", "size": 11083 }, "viewport": { @@ -55,6 +55,6 @@ "receipt": { "algorithm": "sha256", "canonicalization": "UTF-8 JSON; sorted keys; compact separators", - "sha256": "9709eafc99c848f825d083b795a9ba2802109d76b21289e2a4f72c445519c35b" + "sha256": "6495ad5876921dcc8f1c6ad01573507c5107512ca3d1256d3e42f6357ac4f622" } } diff --git a/docs/demo/git-pack-index-v1/manifest.json b/docs/demo/git-pack-index-v1/manifest.json index 4ecdcdc..60ec3f1 100644 --- a/docs/demo/git-pack-index-v1/manifest.json +++ b/docs/demo/git-pack-index-v1/manifest.json @@ -33,7 +33,7 @@ { "path": "docs/demo/git-pack-index-v1/capture-attestation.json", "role": "pack capture provenance and isolation attestation", - "sha256": "18e5fea29af65a0fd15b2959486b282f75425f1dabb1df20a556b57bf3c22757", + "sha256": "724b0c25f4298756385182cbb48a5c260c59051e4f06e21e3495b16c47655b3a", "size": 2011 }, { @@ -69,7 +69,7 @@ ], "capture": { "attestation": "docs/demo/git-pack-index-v1/capture-attestation.json", - "attestation_receipt_sha256": "9709eafc99c848f825d083b795a9ba2802109d76b21289e2a4f72c445519c35b", + "attestation_receipt_sha256": "6495ad5876921dcc8f1c6ad01573507c5107512ca3d1256d3e42f6357ac4f622", "browser_binary": "/ms-playwright/chromium_headless_shell-1193/chrome-linux/headless_shell", "browser_sha256": "003728e0b77eb9d52e4d258594bd55ce22ecd245eb6d3b6858fbd844c901ad7d", "browser_version": "Chromium 140.0.7339.186", @@ -138,14 +138,19 @@ "sha256": "03648331670cdc350fd486b2939e4914e90ee7ca7c2ea2b5cabd4eced21fe766", "size": 2335 }, + { + "path": "tools/generate_evidence.py", + "sha256": "9276b529ec13eaa6ceda1cab1282b6679a689697e5c6930ca17b5e0bc8ba3a92", + "size": 49590 + }, { "path": "tools/generate_pack_evidence.py", - "sha256": "2a85d4e5d3a98cca6e562eae7fad28e5f64d61bd02f973dcffdade274b89514d", - "size": 41315 + "sha256": "234af1ac72189cec9034d3b7f396f6950b01564495208a8891620bb7721ec3a9", + "size": 41376 }, { "path": "tools/capture_pack_report.sh", - "sha256": "3477eeec4a10026fe95b87803f68657069c77f2b491bd69d3cddd56777924f0b", + "sha256": "7cddc4ec1ba66e203195d9a9eb3c454fe39b3790472106bad410cfc9d313ce8f", "size": 11083 } ] From ad69434fb70753f19fe58ab20313a91750d08cb8 Mon Sep 17 00:00:00 2001 From: Omar Ibrahim <31526072+omar07ibrahim@users.noreply.github.com> Date: Sun, 9 Aug 2026 12:54:04 +0000 Subject: [PATCH 5/5] Remove temporary evidence staging workflow --- .../workflows/stage-permission-evidence.yml | 99 ------------------- 1 file changed, 99 deletions(-) delete mode 100644 .github/workflows/stage-permission-evidence.yml diff --git a/.github/workflows/stage-permission-evidence.yml b/.github/workflows/stage-permission-evidence.yml deleted file mode 100644 index 1b588de..0000000 --- a/.github/workflows/stage-permission-evidence.yml +++ /dev/null @@ -1,99 +0,0 @@ -name: Stage permission-hardened evidence (temporary) - -on: - push: - branches: - - agent/harden-evidence-permissions - workflow_dispatch: - -permissions: - contents: read - -concurrency: - group: stage-evidence-permissions-${{ github.ref }} - cancel-in-progress: false - -env: - PYTHONDONTWRITEBYTECODE: "1" - PYTHONNOUSERSITE: "1" - PYTHONHASHSEED: "0" - TZ: UTC - -jobs: - stage: - name: Generate read-only pack evidence artifact - runs-on: ubuntu-24.04 - timeout-minutes: 20 - steps: - - name: Check out the exact feature revision - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - fetch-depth: 1 - persist-credentials: false - ref: ${{ github.sha }} - - - name: Set up exact Python - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 - with: - python-version: "3.12.12" - - - name: Assert the bounded staging context - shell: bash - run: | - set -euo pipefail - test "$GITHUB_REPOSITORY" = "omar07ibrahim/hello-git" - case "$GITHUB_EVENT_NAME" in - push|workflow_dispatch) ;; - *) exit 1 ;; - esac - test "$GITHUB_REF" = "refs/heads/agent/harden-evidence-permissions" - test "$(git rev-parse HEAD)" = "$GITHUB_SHA" - test "$(python -c 'import platform; print(platform.python_version())')" = "3.12.12" - test -z "${OPENAI_API_KEY:-}" - test "$(git status --porcelain=v1 --untracked-files=normal --ignore-submodules=none)" = "" - - - name: Acquire the digest-pinned browser image - shell: bash - run: | - set -euo pipefail - image='mcr.microsoft.com/playwright@sha256:2f29369043d81d6d69a815ceb80760f55e85f5020371ad06a4d996f18503ad1c' - docker pull "$image" - test "$(docker image inspect --format '{{index .RepoDigests 0}}' "$image")" = "$image" - - - name: Generate and independently replay both evidence packages - shell: bash - run: | - set -euo pipefail - tools/capture_report.sh - tools/capture_pack_report.sh - python -B tools/generate_evidence.py --write - python -B tools/generate_evidence.py --check - python -B tools/generate_pack_evidence.py --check - python -W error -m unittest discover -s tests -v - bash -n tools/capture_report.sh tools/capture_pack_report.sh - test "$(shellcheck --version | awk '$1 == "version:" {print $2}')" = "0.9.0" - shellcheck tools/capture_report.sh tools/capture_pack_report.sh - - - name: Upload generated evidence without repository write access - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - with: - name: git-evidence-permission-hardening-${{ github.sha }} - path: | - docs/assets/evidence-pipeline.svg - docs/assets/git-dag-cli.svg - docs/assets/git-dag-report.png - docs/assets/git-dag-topology.svg - docs/assets/git-object-envelope.svg - docs/assets/git-pack-cli.svg - docs/assets/git-pack-fanout.svg - docs/assets/git-pack-integrity.svg - docs/assets/git-pack-layout.svg - docs/assets/git-pack-report.png - docs/demo/git-dag-v1/ - docs/demo/git-pack-index-v1/ - evidence/git-dag-v1.json - evidence/git-pack-index-v1.json - if-no-files-found: error - include-hidden-files: false - compression-level: 0 - retention-days: 1