Skip to content

CI(harden-runner): Add audit fallback for fork PR runs#288

Merged
tykeal merged 1 commit into
lfit:mainfrom
modeseven-lfit:fix/harden-runner-fork-pr-fallback
May 13, 2026
Merged

CI(harden-runner): Add audit fallback for fork PR runs#288
tykeal merged 1 commit into
lfit:mainfrom
modeseven-lfit:fix/harden-runner-fork-pr-fallback

Conversation

@ModeSevenIndustrialSolutions
Copy link
Copy Markdown
Contributor

Summary

Both currently-open PRs to lfit/dependamerge (#277 and #285)
are blocked because they were raised from forks, where the
CONNECTION_WHITELIST repo/org variable is not exposed to the
workflow. When the allowed-endpoints input to
step-security/harden-runner is empty, block-mode egress refuses
every outbound connection — uv installs, audit downloads, image
fetches, etc. all fail before doing useful work.

This PR replaces each existing single harden-runner step with
a conditional pair:

  • block-mode step gated on vars.CONNECTION_WHITELIST != ''
  • audit-mode fallback step gated on
    vars.CONNECTION_WHITELIST == ''

GitHub evaluates both if expressions independently and runs
exactly one step. When the variable is present (push to main,
internal branches) we keep the existing strict block-mode policy
unchanged. When the variable is absent (fork PRs) we fall back
to audit-only, which logs every egress destination without
blocking it so the job still runs. The audit log is still
attached to the run and remains available for review.

Why audit-only for fork PRs

Fork PRs cannot leverage the org-curated whitelist anyway, so
the realistic alternatives are:

  1. Block everything (status quo) — every fork PR fails CI.
    Contributors can't get review feedback on automation
    workflows.
  2. Audit-only fallback (this PR) — fork PRs run normally;
    egress destinations are recorded for post-hoc review.
  3. Hard-coded fork-PR whitelist — would need ongoing
    maintenance and would still drift from the canonical list.

Option 2 is the standard step-security pattern for this case
and matches what other LF projects use.

Sites updated

20 harden-runner blocks across 4 workflow files:

File Blocks
.github/workflows/autolabeler.yaml 1
.github/workflows/build-test-release.yaml 11
.github/workflows/build-test.yaml 7
.github/workflows/release-drafter.yaml 1

Same step-security/harden-runner SHA pin
(a5ad31d6a139d249332a2605b85202e8c0b78450, v2.19.1) preserved
on every site. No other behavioural changes.

Validation

  • actionlint: clean for all modified files.
  • yamllint: clean for all modified files (the 2 remaining
    warnings in openssf-scorecard.yaml are pre-existing and
    unrelated).
  • pre-commit: all hooks pass on the commit.

Once this lands, rebasing #277 and #285 onto main should
unblock their CI.

Diff shape (per-site)

-      # yamllint disable-line rule:line-length
-      - uses: step-security/harden-runner@<sha>  # v2.19.1
-        with:
-          egress-policy: 'block'
-          allowed-endpoints: >
-            ${{ vars.CONNECTION_WHITELIST }}
+      # When the CONNECTION_WHITELIST repo/org variable is exposed
+      # to this run (i.e. not a fork PR), use it to enforce a
+      # block-mode egress policy.
+      - name: 'Harden runner (block egress with whitelist)'
+        if: ${{ vars.CONNECTION_WHITELIST != '' }}
+        # yamllint disable-line rule:line-length
+        uses: step-security/harden-runner@<sha>  # v2.19.1
+        with:
+          egress-policy: 'block'
+          allowed-endpoints: >
+            ${{ vars.CONNECTION_WHITELIST }}
+
+      # Fallback for fork PRs and other contexts where the
+      # CONNECTION_WHITELIST variable is not exposed to the
+      # workflow.  Audit-only mode logs all egress without
+      # blocking it so CI still runs.
+      - name: 'Harden runner (audit fallback, no whitelist available)'
+        if: ${{ vars.CONNECTION_WHITELIST == '' }}
+        # yamllint disable-line rule:line-length
+        uses: step-security/harden-runner@<sha>  # v2.19.1
+        with:
+          egress-policy: 'audit'

Both currently-open PRs to lfit/dependamerge are blocked because
they were raised from forks, where the CONNECTION_WHITELIST
repo/org variable is not exposed to the workflow.  When the
allowed-endpoints input to step-security/harden-runner is empty,
block-mode egress refuses every outbound connection and CI jobs
that need network access (uv installs, audit downloads, image
fetches, etc.) fail before doing useful work.

Replace each existing single harden-runner step with a
conditional pair:

  - block-mode step gated on CONNECTION_WHITELIST != ''
  - audit-mode fallback step gated on CONNECTION_WHITELIST == ''

GitHub evaluates both ifs independently and runs exactly one
step.  When the variable is present (push to main, internal
branches) we keep the existing strict block-mode policy.  When
the variable is absent (fork PRs) we fall back to audit-only,
which logs every egress destination without blocking it so the
job still runs.  The audit log is still attached to the run and
remains available for review.

Same step-security/harden-runner SHA pin
(a5ad31d6a139d249332a2605b85202e8c0b78450, v2.19.1) preserved
on every site.  No other behavioural changes.

Sites updated (20 total):

* .github/workflows/autolabeler.yaml         (1)
* .github/workflows/build-test-release.yaml  (11)
* .github/workflows/build-test.yaml          (7)
* .github/workflows/release-drafter.yaml     (1)

actionlint and yamllint both clean for the modified files.

Co-authored-by: Claude <claude@anthropic.com>
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts CI runner hardening so fork-based pull requests don’t fail due to an unavailable CONNECTION_WHITELIST repo/org variable. It keeps the existing block-mode egress policy when the whitelist is available, and falls back to audit-only mode when it isn’t (e.g., fork PR runs).

Changes:

  • Replace each single step-security/harden-runner block-mode step with two conditional steps:
    • Block-mode with allowed-endpoints when vars.CONNECTION_WHITELIST != ''
    • Audit-only fallback when vars.CONNECTION_WHITELIST == ''
  • Preserve existing action SHA pins and behavior for non-fork contexts where the whitelist is present.
  • Apply the same pattern consistently across all affected workflows.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.

File Description
.github/workflows/autolabeler.yaml Add conditional harden-runner block/audit steps based on CONNECTION_WHITELIST availability.
.github/workflows/build-test-release.yaml Add conditional harden-runner block/audit steps across release workflow jobs to unblock fork PR CI behavior where relevant.
.github/workflows/build-test.yaml Add conditional harden-runner block/audit steps across build/test/audit jobs to avoid fork PR failures.
.github/workflows/release-drafter.yaml Add conditional harden-runner block/audit steps so hardening doesn’t brick runs when whitelist isn’t exposed.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@tykeal tykeal merged commit c43d4e6 into lfit:main May 13, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants