From 9dca250911253ed12daf355617895293aee0ba60 Mon Sep 17 00:00:00 2001 From: ms280690 Date: Mon, 1 Jun 2026 11:52:26 -0700 Subject: [PATCH 1/4] feat(#28): add harden-runner in audit mode to all CI jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add step-security/harden-runner@9af89fc7 (v2.19.4) as the first step in every CI job. Runs in egress-policy: audit — logs all outbound network traffic without blocking. Provides the baseline dataset needed to build an explicit allowlist before switching to enforce mode. Jobs instrumented: actionlint, zizmor, scorecard, dependency-review, terramate-opentofu-setup, storage-optimizer. docs/approved-actions.md: - Add step-security/harden-runner to approved actions table. - Add step-security/* to org allowlist patterns. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/ci.yml | 24 ++++++++++++++++++++++++ docs/approved-actions.md | 4 +++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4a7b7fe..ae28190 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,6 +26,10 @@ jobs: contents: read checks: write steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -40,6 +44,10 @@ jobs: contents: read security-events: write steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -57,6 +65,10 @@ jobs: actions: read security-events: write steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -76,6 +88,10 @@ jobs: contents: read pull-requests: write steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -93,6 +109,10 @@ jobs: permissions: contents: read steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false @@ -109,6 +129,10 @@ jobs: permissions: contents: read steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: + egress-policy: audit + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: persist-credentials: false diff --git a/docs/approved-actions.md b/docs/approved-actions.md index a2f35a1..e08ae8c 100644 --- a/docs/approved-actions.md +++ b/docs/approved-actions.md @@ -25,6 +25,7 @@ This is enforced at: **Org Settings → Actions → General → Allow selected a | `zizmorcore/zizmor-action` | zizmorcore | `5f14fd08` (v0.5.6) | `zizmor` | Zizmor static security analysis; uploads SARIF | 2026-05-21 | | `opentofu/setup-opentofu` | OpenTofu | `847eaa4a` (v2.0.1) | `terramate-opentofu-setup` | Install OpenTofu CLI | 2026-05-21 | | `terramate-io/terramate-action` | Terramate | `c5a13758` (v3.0.0) | `terramate-opentofu-setup` | Install Terramate CLI | 2026-05-21 | +| `step-security/harden-runner` | StepSecurity | `9af89fc7` (v2.19.4) | `ci.yml` (all jobs) | Runner egress monitor — audits outbound network calls; baseline for enforce mode | 2026-06-01 | ## Security review criteria @@ -54,7 +55,7 @@ Before approving a new action, verify all of the following: "github_owned_allowed": true, "verified_allowed": false, "patterns_allowed": [ - "ossf/*", "reviewdog/*", "zizmorcore/*", "opentofu/*", "terramate-io/*", + "ossf/*", "reviewdog/*", "zizmorcore/*", "opentofu/*", "terramate-io/*", "step-security/*", "/*" ] } @@ -74,6 +75,7 @@ reviewdog/* zizmorcore/* opentofu/* terramate-io/* +step-security/* ``` GitHub-owned actions (`actions/*`, `github/*`) are covered by `github_owned_allowed: true` and do not need explicit patterns. From f134a7564c4122453e2c2e10e49c36e3ec1f9172 Mon Sep 17 00:00:00 2001 From: ms280690 Date: Mon, 1 Jun 2026 12:59:11 -0700 Subject: [PATCH 2/4] Update docs for usage Signed-off-by: ms280690 --- README.md | 105 +++++++++++++++++++++++++++++++++++++++ docs/approved-actions.md | 34 +++++++++++++ 2 files changed, 139 insertions(+) diff --git a/README.md b/README.md index 4187361..15c8a0d 100644 --- a/README.md +++ b/README.md @@ -130,6 +130,111 @@ steps: The action will fail the job if `terramate generate` produces uncommitted output, ensuring generated files are always in sync with the source of truth. +## Consuming repo CI setup + +Public and private repos use different subsets of these actions. The key differences are `harden-runner` (sends egress telemetry to StepSecurity — omit on private repos) and `scorecard` (requires public visibility to produce meaningful scores). + +### Public repo + +```yaml +name: CI +on: + push: + branches: [main] + pull_request: + schedule: + - cron: '0 6 * * 1' +permissions: + contents: read +jobs: + actionlint: + runs-on: ubuntu-latest + permissions: { contents: read, checks: write } + steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: { egress-policy: audit } + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/github-actionlint@ + + zizmor: + runs-on: ubuntu-latest + permissions: { contents: read, security-events: write } + steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: { egress-policy: audit } + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/zizmor@ + + scorecard: # public repos only — checks degrade on private repos + runs-on: ubuntu-latest + if: github.ref == 'refs/heads/main' + permissions: { contents: read, actions: read, security-events: write } + steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: { egress-policy: audit } + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/scorecard@ + + dependency-review: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + permissions: { contents: read, pull-requests: write } + steps: + - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + with: { egress-policy: audit } + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/dependency-review@ +``` + +### Private repo + +Same structure — drop `harden-runner` from every job and drop the `scorecard` job entirely: + +```yaml +name: CI +on: + push: + branches: [main] + pull_request: +permissions: + contents: read +jobs: + actionlint: + runs-on: ubuntu-latest + permissions: { contents: read, checks: write } + steps: + # harden-runner omitted — sends egress telemetry to StepSecurity (third party) + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/github-actionlint@ + + zizmor: + runs-on: ubuntu-latest + permissions: { contents: read, security-events: write } + # security-events: write requires GitHub Advanced Security on private repos + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/zizmor@ + + # scorecard omitted — most checks require public repo visibility + + dependency-review: + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + permissions: { contents: read, pull-requests: write } + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: { persist-credentials: false } + - uses: sparkgeo/github-actions/.github/actions/dependency-review@ +``` + +See [docs/approved-actions.md](docs/approved-actions.md) for full data handling and telemetry details. + ## Security This repo is part of the Sparkgeo GitHub Actions security programme. The pillars are: diff --git a/docs/approved-actions.md b/docs/approved-actions.md index e08ae8c..9cdd21e 100644 --- a/docs/approved-actions.md +++ b/docs/approved-actions.md @@ -27,6 +27,40 @@ This is enforced at: **Org Settings → Actions → General → Allow selected a | `terramate-io/terramate-action` | Terramate | `c5a13758` (v3.0.0) | `terramate-opentofu-setup` | Install Terramate CLI | 2026-05-21 | | `step-security/harden-runner` | StepSecurity | `9af89fc7` (v2.19.4) | `ci.yml` (all jobs) | Runner egress monitor — audits outbound network calls; baseline for enforce mode | 2026-06-01 | +## Data handling and third-party telemetry + +### step-security/harden-runner + +`harden-runner` sends network egress telemetry to StepSecurity's platform (app.stepsecurity.io). This is the mechanism that powers the dashboard — it is not a side effect. + +**Data sent to StepSecurity:** +- Repository name and organisation +- Workflow run ID, job name, step name +- Outbound connection metadata: destination hostname/IP, port, process name, timestamp + +**Data NOT sent:** secrets, environment variables, source code, file contents. + +**Implications by repo visibility:** + +| Repo type | Risk | Recommendation | +|---|---|---| +| Public | Low — repo name/structure already public | Acceptable; use `egress-policy: audit` to build endpoint allowlist | +| Private | Medium — org name + CI topology exposed to StepSecurity | Review [StepSecurity privacy policy](https://www.stepsecurity.io/privacy) and data processing terms before adopting; if org policy prohibits third-party CI telemetry, omit this action | + +There is no mode that suppresses telemetry while keeping the dashboard — if data leaving GitHub is unacceptable, remove `harden-runner` entirely and enforce egress via network-level controls instead. + +### Decision: private repo usage + +For private repos, the recommendation is to **omit `harden-runner` entirely** from consuming workflows. There is no configuration option that suppresses telemetry while keeping monitoring — the two are inseparable. + +Alternatives for private repos that need egress control: + +- **GitHub Enterprise Cloud (GHEC) Actions network configurations** — network-layer egress control; data stays within GitHub/Azure infrastructure; requires a GHEC subscription (approximately $21/user/month). +- **Self-hosted runners with firewall rules** — egress data stays in your own infrastructure; trades StepSecurity dependency for additional ops overhead managing the runner fleet. +- **StepSecurity Enterprise (self-hosted backend)** — licensed product where the runner agent connects to your own server rather than app.stepsecurity.io; eliminates third-party data sharing but requires procuring and operating the backend. + +For static pre-run security analysis on private repos, **zizmor + actionlint** (already included in this repo) provide workflow security coverage without any outbound egress, and should be considered sufficient for the static analysis layer. + ## Security review criteria Before approving a new action, verify all of the following: From 27981a64f9f9438e73ad2278a8566a5f3e125549 Mon Sep 17 00:00:00 2001 From: ms280690 Date: Mon, 1 Jun 2026 13:09:12 -0700 Subject: [PATCH 3/4] add name Signed-off-by: ms280690 --- .github/workflows/ci.yml | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ae28190..ff19944 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,8 @@ jobs: contents: read checks: write steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit @@ -44,7 +45,8 @@ jobs: contents: read security-events: write steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit @@ -65,7 +67,8 @@ jobs: actions: read security-events: write steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit @@ -88,7 +91,8 @@ jobs: contents: read pull-requests: write steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit @@ -109,7 +113,8 @@ jobs: permissions: contents: read steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit @@ -129,7 +134,8 @@ jobs: permissions: contents: read steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - name: Harden the runner (Audit all outbound calls) + uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 with: egress-policy: audit From 95ae40c5026e9d3f056ec480f8033e206c796379 Mon Sep 17 00:00:00 2001 From: ms280690 Date: Mon, 1 Jun 2026 13:37:42 -0700 Subject: [PATCH 4/4] replace actual SHA Signed-off-by: ms280690 --- README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 15c8a0d..fa86d16 100644 --- a/README.md +++ b/README.md @@ -151,9 +151,9 @@ jobs: runs-on: ubuntu-latest permissions: { contents: read, checks: write } steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - uses: step-security/harden-runner@ with: { egress-policy: audit } - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/github-actionlint@ @@ -161,9 +161,9 @@ jobs: runs-on: ubuntu-latest permissions: { contents: read, security-events: write } steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - uses: step-security/harden-runner@ with: { egress-policy: audit } - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/zizmor@ @@ -172,9 +172,9 @@ jobs: if: github.ref == 'refs/heads/main' permissions: { contents: read, actions: read, security-events: write } steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - uses: step-security/harden-runner@ with: { egress-policy: audit } - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/scorecard@ @@ -183,9 +183,9 @@ jobs: if: github.event_name == 'pull_request' permissions: { contents: read, pull-requests: write } steps: - - uses: step-security/harden-runner@9af89fc71515a100421586dfdb3dc9c984fbf411 # v2.19.4 + - uses: step-security/harden-runner@ with: { egress-policy: audit } - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/dependency-review@ ``` @@ -208,7 +208,7 @@ jobs: permissions: { contents: read, checks: write } steps: # harden-runner omitted — sends egress telemetry to StepSecurity (third party) - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/github-actionlint@ @@ -217,7 +217,7 @@ jobs: permissions: { contents: read, security-events: write } # security-events: write requires GitHub Advanced Security on private repos steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/zizmor@ @@ -228,7 +228,7 @@ jobs: if: github.event_name == 'pull_request' permissions: { contents: read, pull-requests: write } steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@ with: { persist-credentials: false } - uses: sparkgeo/github-actions/.github/actions/dependency-review@ ```