From 568e3dec6c2af3174f9681a3816fe7330924023a Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 30 Sep 2026 15:30:37 +0100 Subject: [PATCH 1/3] ci: adopt harden-runner in standards-only workflows (#941) Owner ruling 2026-09-30: adopt step-security/harden-runner. This lands it in the six workflows that execute only in this repo (apply-workflow- pins, lockfile-drift-detect, propagate-hooks, settings-drift-detect, signed-push-smoke, tag-ruleset-canon), clearing their RE001 findings. - propagate-hooks runs on a protected-branch push, so it uses egress-policy: block with the GitHub endpoints it actually needs, rather than audit (which Hypatia RE002 flags high). - actions.lock lists harden-runner for those six workflows, and `gh actions-lock --no-fix` verifies it (the signed-push-smoke local-action failure predates this change). - The six now-fixed RE001 entries are removed from .hypatia-baseline.json. The reusable (*-reusable.yml) and consumer-copied workflows (labels, label-triage, boj-build, instant-sync) are deliberately untouched. A new action there becomes a dependency that every consumer's actions.lock must list first, otherwise the job fails at startup with no check run. No allowlist change is needed: StepSecurity is a Marketplace verified creator and the canon policy has verified_allowed: true. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01QFphKkDVB9pUDSCD4bkz65 --- .github/workflows/actions.lock | 11 +++++ .github/workflows/apply-workflow-pins.yml | 4 ++ .github/workflows/lockfile-drift-detect.yml | 4 ++ .github/workflows/propagate-hooks.yml | 22 +++++++++ .github/workflows/settings-drift-detect.yml | 4 ++ .github/workflows/signed-push-smoke.yml | 4 ++ .github/workflows/tag-ruleset-canon.yml | 4 ++ .hypatia-baseline.json | 54 --------------------- 8 files changed, 53 insertions(+), 54 deletions(-) diff --git a/.github/workflows/actions.lock b/.github/workflows/actions.lock index 68939b28a..cb48c492e 100644 --- a/.github/workflows/actions.lock +++ b/.github/workflows/actions.lock @@ -14,6 +14,7 @@ workflows: - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1' - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + - 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1' '.github/workflows/boj-build.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' '.github/workflows/canon-spine-lockstep.yml': @@ -84,6 +85,7 @@ workflows: '.github/workflows/lockfile-drift-detect.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + - 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1' '.github/workflows/makefile-blocker.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' '.github/workflows/mirror-reusable.yml': @@ -106,6 +108,7 @@ workflows: - 'actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9' '.github/workflows/propagate-hooks.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' + - 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1' '.github/workflows/readme-derive-reusable.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' '.github/workflows/readme-derive.yml': [] @@ -136,16 +139,19 @@ workflows: '.github/workflows/settings-drift-detect.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + - 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1' '.github/workflows/signed-push-smoke.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1' - 'asana/push-signed-commits@d615ca88d8e1a946734c24970d1e7a6c56f34897' + - 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1' '.github/workflows/spark-theatre-gate.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' '.github/workflows/tag-ruleset-canon.yml': - 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1' - 'actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1' - 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a' + - 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1' '.github/workflows/tailscale-connect-reusable.yml': - 'tailscale/github-action@d1b6cd204f8dceda5b3eaad7f1f767be390056cd' dependencies: @@ -258,6 +264,11 @@ dependencies: commit: 'sha1-28959ce8df70de7be546dd1250a005dd32156697' owner_id: 18365890 repo_id: 220359305 + 'step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1': + ref: 'v2.21.1' + commit: 'sha1-e14015d583714f6e62063499dc959a02595150a1' + owner_id: 88700172 + repo_id: 422287306 'swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6': ref: '6323deb102c322ba6fcbdcafc7e3dddab59af2b6' commit: 'sha1-6323deb102c322ba6fcbdcafc7e3dddab59af2b6' diff --git a/.github/workflows/apply-workflow-pins.yml b/.github/workflows/apply-workflow-pins.yml index 3172093e9..88406d79b 100644 --- a/.github/workflows/apply-workflow-pins.yml +++ b/.github/workflows/apply-workflow-pins.yml @@ -55,6 +55,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 60 steps: + - name: Harden runner (egress audit) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + egress-policy: audit - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # WHICH App's credentials belong in vars.APP_ID / secrets.APP_PRIVATE_KEY: diff --git a/.github/workflows/lockfile-drift-detect.yml b/.github/workflows/lockfile-drift-detect.yml index 16745f217..438fb0840 100644 --- a/.github/workflows/lockfile-drift-detect.yml +++ b/.github/workflows/lockfile-drift-detect.yml @@ -49,6 +49,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 45 steps: + - name: Harden runner (egress audit) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + egress-policy: audit - name: Checkout standards (for the checker script) uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 diff --git a/.github/workflows/propagate-hooks.yml b/.github/workflows/propagate-hooks.yml index 24bfa73c4..82362b62a 100644 --- a/.github/workflows/propagate-hooks.yml +++ b/.github/workflows/propagate-hooks.yml @@ -50,6 +50,17 @@ jobs: dry_run: ${{ steps.config.outputs.dry_run }} steps: + - name: Harden runner (egress block) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + # Runs on a protected-branch push (RE002): block, not audit. This + # job only talks to GitHub (checkout, the REST API, git transport). + egress-policy: block + allowed-endpoints: > + github.com:443 + api.github.com:443 + codeload.github.com:443 + objects.githubusercontent.com:443 - name: Checkout standards repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: @@ -177,6 +188,17 @@ jobs: fail-fast: false # Don't stop on individual failures steps: + - name: Harden runner (egress block) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + # Runs on a protected-branch push (RE002): block, not audit. This + # job only talks to GitHub (checkout, the REST API, git transport). + egress-policy: block + allowed-endpoints: > + github.com:443 + api.github.com:443 + codeload.github.com:443 + objects.githubusercontent.com:443 - name: Checkout standards repository uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/settings-drift-detect.yml b/.github/workflows/settings-drift-detect.yml index ab4d6170a..3f61651de 100644 --- a/.github/workflows/settings-drift-detect.yml +++ b/.github/workflows/settings-drift-detect.yml @@ -58,6 +58,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 45 steps: + - name: Harden runner (egress audit) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + egress-policy: audit - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 diff --git a/.github/workflows/signed-push-smoke.yml b/.github/workflows/signed-push-smoke.yml index a016b5c56..3d86434c9 100644 --- a/.github/workflows/signed-push-smoke.yml +++ b/.github/workflows/signed-push-smoke.yml @@ -27,6 +27,10 @@ jobs: permissions: contents: write steps: + - name: Harden runner (egress audit) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + egress-policy: audit - name: Checkout uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: diff --git a/.github/workflows/tag-ruleset-canon.yml b/.github/workflows/tag-ruleset-canon.yml index 08ce32fb8..119893d89 100644 --- a/.github/workflows/tag-ruleset-canon.yml +++ b/.github/workflows/tag-ruleset-canon.yml @@ -43,6 +43,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 10 steps: + - name: Harden runner (egress audit) + uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 + with: + egress-policy: audit - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # WHICH App's credentials belong in vars.APP_ID / secrets.APP_PRIVATE_KEY: diff --git a/.hypatia-baseline.json b/.hypatia-baseline.json index fcd874c2b..c113d25be 100644 --- a/.hypatia-baseline.json +++ b/.hypatia-baseline.json @@ -1013,15 +1013,6 @@ "expires_at": "2026-12-22", "tracking_issue": "hyperpolymath/standards#944" }, - { - "severity": "warn", - "rule_module": "research_extensions", - "type": "RE001", - "file": ".github/workflows/signed-push-smoke.yml", - "note": "ESTATE DECISION PENDING (hypatia triage 2026-09-22): adopt step-security/harden-runner or record a principled WONTFIX; the estate uses it nowhere today.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#941" - }, { "severity": "warn", "rule_module": "research_extensions", @@ -1031,15 +1022,6 @@ "expires_at": "2026-12-22", "tracking_issue": "hyperpolymath/standards#941" }, - { - "severity": "warn", - "rule_module": "research_extensions", - "type": "RE001", - "file": ".github/workflows/settings-drift-detect.yml", - "note": "ESTATE DECISION PENDING (hypatia triage 2026-09-22): adopt step-security/harden-runner or record a principled WONTFIX; the estate uses it nowhere today.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#941" - }, { "severity": "warn", "rule_module": "research_extensions", @@ -1094,24 +1076,6 @@ "expires_at": "2026-12-22", "tracking_issue": "hyperpolymath/standards#941" }, - { - "severity": "warn", - "rule_module": "research_extensions", - "type": "RE001", - "file": ".github/workflows/apply-workflow-pins.yml", - "note": "ESTATE DECISION PENDING (hypatia triage 2026-09-22): adopt step-security/harden-runner or record a principled WONTFIX; the estate uses it nowhere today.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#941" - }, - { - "severity": "warn", - "rule_module": "research_extensions", - "type": "RE001", - "file": ".github/workflows/propagate-hooks.yml", - "note": "ESTATE DECISION PENDING (hypatia triage 2026-09-22): adopt step-security/harden-runner or record a principled WONTFIX; the estate uses it nowhere today.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#941" - }, { "severity": "warn", "rule_module": "research_extensions", @@ -1121,24 +1085,6 @@ "expires_at": "2026-12-22", "tracking_issue": "hyperpolymath/standards#941" }, - { - "severity": "warn", - "rule_module": "research_extensions", - "type": "RE001", - "file": ".github/workflows/tag-ruleset-canon.yml", - "note": "ESTATE DECISION PENDING (hypatia triage 2026-09-22): adopt step-security/harden-runner or record a principled WONTFIX; the estate uses it nowhere today.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#941" - }, - { - "severity": "warn", - "rule_module": "research_extensions", - "type": "RE001", - "file": ".github/workflows/lockfile-drift-detect.yml", - "note": "ESTATE DECISION PENDING (hypatia triage 2026-09-22): adopt step-security/harden-runner or record a principled WONTFIX; the estate uses it nowhere today.", - "expires_at": "2026-12-22", - "tracking_issue": "hyperpolymath/standards#941" - }, { "severity": "warn", "rule_module": "research_extensions", From 54f6d805e60371ab7d8b205842ba3d912dc08cd0 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Wed, 30 Sep 2026 16:25:35 +0100 Subject: [PATCH 2/3] ci: allowlist step-security/harden-runner (#941) The Allowlist Preflight on this PR reported harden-runner as a GAP: check-allowed-actions.sh matches `uses:` refs against patterns_allowed only and does not know which creators are Marketplace-verified, so `verified_allowed: true` does not satisfy it. Per the allowlist README ("add a pattern here when the estate adopts a new action"), list it in the canonical allowed-actions.json and in config/settings/ actions-allowlist.json, which set-allowed-actions.sh applies. Locally: check-allowed-actions.sh reports 0 of 37 refs uncovered. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01QFphKkDVB9pUDSCD4bkz65 --- config/settings/actions-allowlist.json | 1 + .../actions-allowlist/allowed-actions.json | 1 + 2 files changed, 2 insertions(+) diff --git a/config/settings/actions-allowlist.json b/config/settings/actions-allowlist.json index 6cf44cfdd..92221d975 100644 --- a/config/settings/actions-allowlist.json +++ b/config/settings/actions-allowlist.json @@ -115,6 +115,7 @@ "softprops/action-gh-release@*", "SonarSource/sonarcloud-github-action@*", "SonarSource/sonarqube-scan-action@*", + "step-security/harden-runner@*", "superfly/flyctl-actions/setup-flyctl@*", "Swatinem/rust-cache@*", "swatinem/rust-cache@*", diff --git a/rhodium-standard-repositories/actions-allowlist/allowed-actions.json b/rhodium-standard-repositories/actions-allowlist/allowed-actions.json index 268d4ee2d..777a2ee7e 100644 --- a/rhodium-standard-repositories/actions-allowlist/allowed-actions.json +++ b/rhodium-standard-repositories/actions-allowlist/allowed-actions.json @@ -86,6 +86,7 @@ "softprops/action-gh-release@*", "SonarSource/sonarcloud-github-action@*", "SonarSource/sonarqube-scan-action@*", + "step-security/harden-runner@*", "Swatinem/rust-cache@*", "taiki-e/install-action@*", "trufflesecurity/trufflehog@*", From a88961063d5fa090aab317d89e1370fe956f86d8 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 1 Oct 2026 12:06:27 +0100 Subject: [PATCH 3/3] chore(registry): regenerate after RSR allowlist change (#941) allowed-actions.json lives under the RSR spec home, so adding harden-runner moves that spec's source_hash. Regenerated with scripts/build-registry.sh; --check, build-registry-test.sh and build-scorecards.sh --check --strict --verify all pass locally. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01QFphKkDVB9pUDSCD4bkz65 --- .machine_readable/REGISTRY.a2ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.machine_readable/REGISTRY.a2ml b/.machine_readable/REGISTRY.a2ml index 82172235a..3cfea210a 100644 --- a/.machine_readable/REGISTRY.a2ml +++ b/.machine_readable/REGISTRY.a2ml @@ -207,7 +207,7 @@ name = "RSR — Rhodium Standard Repositories" stream = "governance" home = "rhodium-standard-repositories/" canonical_doc = "rhodium-standard-repositories/README.adoc" -source_hash = "sha256:51b38eb327df7ea430078bd75566d15ab9a6618f19a3b9ee7c2a1cfb8ce6adda" +source_hash = "sha256:3c7ccbf889b32ffac7566dcdf93ea9923d1b53f1c6055889f4a330a52c421d85" route = "the repository-compliance standard every repo is graded against" [[spec]]