From 4b80d22cb01ee0b8068c59d5e0fff2ce7c60fb63 Mon Sep 17 00:00:00 2001 From: Frenchie Date: Sun, 5 Jul 2026 17:47:12 +1000 Subject: [PATCH] ci: flip harden-runner to egress block mode with per-job allowlists (SLSA phase 5) Every job moves from egress-policy: audit to block with an explicit allowed-endpoints list: the job's observed egress baseline (StepSecurity insights across the runs since phase 4 landed) plus GitHub/Go-infra cache-miss paths the same tools use. The release job has not yet run under harden-runner; its list adds the publish endpoints (release upload, Sigstore keyless signing) to the shared build baseline, and its attest step runs before gh release create, so a blocked endpoint fails the run before anything is published. This PR's own CI validates the block lists live for every pull_request-triggered job. Co-Authored-By: Claude Fable 5 --- .github/workflows/codeql.yml | 18 ++++++++++++++++-- .github/workflows/dependency-review.yml | 14 ++++++++++++-- .github/workflows/govulncheck.yml | 18 ++++++++++++++++-- .github/workflows/release.yml | 23 +++++++++++++++++++++-- .github/workflows/testvet.yml | 17 +++++++++++++++-- .github/workflows/zizmor.yml | 14 ++++++++++++-- docs/SLSA.md | 14 +++++++++++++- 7 files changed, 105 insertions(+), 13 deletions(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 9c1cdc6..24e73a2 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -26,10 +26,24 @@ jobs: packages: read # fetch CodeQL query packs contents: read steps: - - name: Harden runner (egress audit) + - name: Harden runner (egress block) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + *.actions.githubusercontent.com:443 + api.github.com:443 + codeload.github.com:443 + dl.google.com:443 + github.com:443 + go.dev:443 + objects.githubusercontent.com:443 + proxy.golang.org:443 + raw.githubusercontent.com:443 + release-assets.githubusercontent.com:443 + storage.googleapis.com:443 + sum.golang.org:443 + uploads.github.com:443 - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml index e27b9af..88e1b65 100644 --- a/.github/workflows/dependency-review.yml +++ b/.github/workflows/dependency-review.yml @@ -15,10 +15,20 @@ jobs: dependency-review: runs-on: ubuntu-latest steps: - - name: Harden runner (egress audit) + - name: Harden runner (egress block) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + *.actions.githubusercontent.com:443 + api.deps.dev:443 + api.github.com:443 + api.securityscorecards.dev:443 + codeload.github.com:443 + github.com:443 + objects.githubusercontent.com:443 + raw.githubusercontent.com:443 + release-assets.githubusercontent.com:443 - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/.github/workflows/govulncheck.yml b/.github/workflows/govulncheck.yml index 26af062..311f69b 100644 --- a/.github/workflows/govulncheck.yml +++ b/.github/workflows/govulncheck.yml @@ -21,10 +21,24 @@ jobs: govulncheck: runs-on: ubuntu-latest steps: - - name: Harden runner (egress audit) + - name: Harden runner (egress block) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + *.actions.githubusercontent.com:443 + api.github.com:443 + codeload.github.com:443 + dl.google.com:443 + github.com:443 + go.dev:443 + objects.githubusercontent.com:443 + proxy.golang.org:443 + raw.githubusercontent.com:443 + release-assets.githubusercontent.com:443 + storage.googleapis.com:443 + sum.golang.org:443 + vuln.go.dev:443 - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b2daef2..bc8e7a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -18,10 +18,29 @@ jobs: id-token: write # OIDC token for Sigstore signing of provenance attestations: write # store the build-provenance attestation steps: - - name: Harden runner (egress audit) + - name: Harden runner (egress block) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + *.actions.githubusercontent.com:443 + api.github.com:443 + codeload.github.com:443 + dl.google.com:443 + fulcio.sigstore.dev:443 + get.anchore.io:443 + github.com:443 + go.dev:443 + objects.githubusercontent.com:443 + proxy.golang.org:443 + raw.githubusercontent.com:443 + rekor.sigstore.dev:443 + release-assets.githubusercontent.com:443 + storage.googleapis.com:443 + sum.golang.org:443 + toolbox-data.anchore.io:443 + tuf-repo-cdn.sigstore.dev:443 + uploads.github.com:443 - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/.github/workflows/testvet.yml b/.github/workflows/testvet.yml index 06b15e4..5dbf4fd 100644 --- a/.github/workflows/testvet.yml +++ b/.github/workflows/testvet.yml @@ -9,10 +9,23 @@ jobs: testvet: runs-on: ubuntu-latest steps: - - name: Harden runner (egress audit) + - name: Harden runner (egress block) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + *.actions.githubusercontent.com:443 + api.github.com:443 + codeload.github.com:443 + dl.google.com:443 + github.com:443 + go.dev:443 + objects.githubusercontent.com:443 + proxy.golang.org:443 + raw.githubusercontent.com:443 + release-assets.githubusercontent.com:443 + storage.googleapis.com:443 + sum.golang.org:443 - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index eaee11f..2b8f8ab 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -20,10 +20,20 @@ jobs: contents: read security-events: write # upload SARIF findings to code scanning steps: - - name: Harden runner (egress audit) + - name: Harden runner (egress block) uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: - egress-policy: audit + egress-policy: block + allowed-endpoints: > + *.actions.githubusercontent.com:443 + api.github.com:443 + codeload.github.com:443 + ghcr.io:443 + github.com:443 + objects.githubusercontent.com:443 + pkg-containers.githubusercontent.com:443 + raw.githubusercontent.com:443 + release-assets.githubusercontent.com:443 - name: Checkout uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: diff --git a/docs/SLSA.md b/docs/SLSA.md index 3da3134..cf58741 100644 --- a/docs/SLSA.md +++ b/docs/SLSA.md @@ -5,11 +5,13 @@ Software Artifacts) posture of `github.com/threatcl/spec`. It states where we are today, where we're going, and maps every planned change to a specific SLSA **track** and **level**. -> **Status:** Phases 0–4 complete. Phase 2 rulesets are active on the repo +> **Status:** Phases 0–5 complete. Phase 2 rulesets are active on the repo > (commit + tag signing in force); the first attested release is produced when > the next `vX.Y.Z` tag is pushed (see [Verification](#verification)). Phase 4 > adds scanning (govulncheck, dependency-review, zizmor, CodeQL), runner > hardening, and per-release SBOMs — mirroring `threatcl/threatcl`'s phase 5. +> Phase 5 flips harden-runner from egress *auditing* to egress *enforcement* +> (`block` + per-job `allowed-endpoints`) on every workflow job. ## What this repo is (and why it matters for SLSA) @@ -103,6 +105,7 @@ Source and Build tracks trustworthy (and improve OpenSSF Scorecard). | **4** | CodeQL with `security-extended` | Hygiene — SAST over the library source | | **4** | harden-runner (egress audit) + `persist-credentials: false` on every job | Hygiene — runner egress visibility; no ambient git credentials after checkout | | **4** | SPDX SBOM per released archive (checksummed + attested) | Strengthens Build-track artifact transparency | +| **5** | harden-runner `egress-policy: block` + per-job `allowed-endpoints` on every job | Hygiene — egress *enforcement*: a compromised dependency or action can no longer exfiltrate to arbitrary hosts | ### Caveat on "Build L3" via native GitHub attestations @@ -150,6 +153,15 @@ bounded — the high-value compiled-binary provenance belongs downstream in the `golang.org/x/net` (v0.55.0), and `github.com/go-jose/go-jose/v4` (v4.1.4). All new actions are SHA-pinned with version comments and least-privilege `permissions`. +- [x] **Phase 5** — Egress enforcement (mirrors `threatcl/threatcl` phase 6): + every job's harden-runner flipped from `egress-policy: audit` to `block` + with an explicit per-job `allowed-endpoints` list, derived from the + StepSecurity audit baselines observed since Phase 4 landed, plus + documented cache-miss paths (Go toolchain/module infra) and, for the + release job — which has not yet run under harden-runner — the publish + endpoints (release upload, Sigstore keyless signing). If a release fails + on a blocked endpoint, fix the list on `main` and re-tag the next patch + version; a failed run publishes nothing. ## Maintainer checklist — GitHub settings (Phase 2)