From a2a2dc90b47a4d68a0a74f1fa5d59eb253c3690e Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 20 Jun 2026 07:21:12 +0000 Subject: [PATCH] fix(security): scorecard job permissions, dispatch secret-gate, .envrc placeholder Addresses pre-existing Hypatia workflow_audit findings (unrelated to the timeout PR): - scorecard.yml: add explicit least-privilege job permissions to the OpenSSF Scorecard reusable-workflow caller (was inheriting top-level read-all, which can't grant the security-events/id-token writes publishing needs). Clears scorecard_wrapper_missing_job_permissions. - instant-sync.yml: presence-gate the repository-dispatch step on FARM_DISPATCH_TOKEN (mapped to a job env var, since secrets can't be used in if:) so forks skip it instead of firing with an empty token. Clears secret_action_without_presence_gate. - .envrc: substitute the unsubstituted {{PROJECT_NAME}} scaffold placeholder with the real project name. Deferred: SHA-pinning governance.yml's governance-reusable.yml@main needs the standards@main commit SHA, and the standards repo is out of this session's scope. The critical .envrc 'Generic API key' finding is a false positive (a commented-out '# export API_KEY="..."' placeholder on line 24; gitleaks and trufflehog both pass). Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Y2MWTAqX2x7goVJzjFB4j5 --- .envrc | 2 +- .github/workflows/instant-sync.yml | 8 ++++++++ .github/workflows/scorecard.yml | 8 ++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.envrc b/.envrc index 0b5b702..55ae305 100644 --- a/.envrc +++ b/.envrc @@ -18,7 +18,7 @@ if has nix && [ -f flake.nix ]; then fi # Project environment variables -export PROJECT_NAME="{{PROJECT_NAME}}" +export PROJECT_NAME="wokelangiser" export RSR_TIER="infrastructure" # export DATABASE_URL="..." # export API_KEY="..." diff --git a/.github/workflows/instant-sync.yml b/.github/workflows/instant-sync.yml index 01646a7..6502b8c 100644 --- a/.github/workflows/instant-sync.yml +++ b/.github/workflows/instant-sync.yml @@ -15,8 +15,15 @@ jobs: dispatch: runs-on: ubuntu-latest timeout-minutes: 15 + # Presence-gate: `secrets` can't be referenced directly in `if:`, so the + # token is mapped to a job-level env var the steps guard on. On forks + # (where FARM_DISPATCH_TOKEN is unset) the dispatch is skipped instead of + # firing with an empty token. + env: + FARM_DISPATCH_TOKEN: ${{ secrets.FARM_DISPATCH_TOKEN }} steps: - name: Trigger Propagation + if: ${{ env.FARM_DISPATCH_TOKEN != '' }} uses: peter-evans/repository-dispatch@28959ce8df70de7be546dd1250a005dd32156697 # v3 with: token: ${{ secrets.FARM_DISPATCH_TOKEN }} @@ -31,4 +38,5 @@ jobs: } - name: Confirm + if: ${{ env.FARM_DISPATCH_TOKEN != '' }} run: echo "::notice::Propagation triggered for ${{ github.event.repository.name }}" diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml index fc907c2..b14a058 100644 --- a/.github/workflows/scorecard.yml +++ b/.github/workflows/scorecard.yml @@ -12,5 +12,13 @@ permissions: read-all jobs: analysis: + # Least-privilege scopes for the OpenSSF Scorecard reusable workflow + # (was inheriting the top-level read-all, which can't grant the writes + # publishing needs). Caps what the reusable workflow can request. + permissions: + contents: read + security-events: write + id-token: write + actions: read uses: hyperpolymath/standards/.github/workflows/scorecard-reusable.yml@e0caf11508a3989574713c78f5f444f2ce5e33ef secrets: inherit