From 3c42744213bc2decc25e5f7446d8ce5b8b0b48a5 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 1 Oct 2026 13:58:41 +0100 Subject: [PATCH 1/2] ci(secret-scan): canonical estate scanner caller, key scan (D243) Secret-Scan-Floor (D243/D244) requires the context `scan / gitleaks` estate-wide. The previous inline scanner jobs emitted bare contexts (e.g. `gitleaks`) that cannot satisfy the floor; the reusable deliberately drops TruffleHog as redundant with gitleaks. Write the canonical caller: job key `scan`, reusable pinned to standards@74d2f66, push trigger on the default branch `main`. actionlint: new file clean (findings in previous file: 1). Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0136eszqrQ53Kj7aBH1D4rXK --- .github/workflows/secret-scanner.yml | 62 +++++++--------------------- 1 file changed, 16 insertions(+), 46 deletions(-) diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index c0390ca..f04a556 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -1,57 +1,27 @@ # SPDX-License-Identifier: MPL-2.0 +# Prevention workflow - scans for hardcoded secrets before they reach main. +# +# Calls the estate's shared secret scanner (gitleaks + rust-secrets + +# shell-secrets). The job key MUST stay `scan`: the estate-wide +# Secret-Scan-Floor ruleset requires the check context `scan / gitleaks`. +# +# `secrets: inherit` is REQUIRED - without it the gitleaks action's inner +# secrets.GITHUB_TOKEN is empty and the scan silently degrades. name: Secret Scanner + on: pull_request: push: branches: [main] -# Estate guardrail: cancel superseded runs so re-pushes / rebased PR -# updates do not pile up queued runs against the shared account-wide -# Actions concurrency pool. Applied only to read-only check workflows -# (no publish/mutation), so cancelling a superseded run is always safe. + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true -permissions: read-all -jobs: - trufflehog: - runs-on: ubuntu-latest - timeout-minutes: 15 - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4 - with: - fetch-depth: 0 # Full history for scanning - - name: TruffleHog Secret Scan - uses: trufflesecurity/trufflehog@8a8ef8526528d8a4ff3e2c90be08e25ef8efbd9b # v3 - with: - extra_args: --only-verified --fail - # Rust-specific: Check for hardcoded crypto values - rust-secrets: - runs-on: ubuntu-latest - timeout-minutes: 15 - if: hashFiles('**/Cargo.toml') != '' - steps: - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v4 - - name: Check for hardcoded secrets in Rust - run: | - # Patterns that suggest hardcoded secrets - PATTERNS=( - 'const.*SECRET.*=.*"' - 'const.*KEY.*=.*"[a-zA-Z0-9]{16,}"' - 'const.*TOKEN.*=.*"' - 'let.*api_key.*=.*"' - 'HMAC.*"[a-fA-F0-9]{32,}"' - 'password.*=.*"[^"]+"' - ) - found=0 - for pattern in "${PATTERNS[@]}"; do - if grep -rn --include="*.rs" -E "$pattern" src/; then - echo "WARNING: Potential hardcoded secret found matching: $pattern" - found=1 - fi - done +permissions: + contents: read - if [ $found -eq 1 ]; then - echo "::error::Potential hardcoded secrets detected. Use environment variables instead." - exit 1 - fi +jobs: + scan: + uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@74d2f66f575246cf6e313ae7775f44df6e097ff2 + secrets: inherit From 31d967d7541f75ddcfac549a9ffa185f108bd300 Mon Sep 17 00:00:00 2001 From: "Jonathan D.A. Jewell" <6759885+hyperpolymath@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:05:30 +0100 Subject: [PATCH 2/2] ci(secret-scan): drop secrets: inherit from the scanner caller (least privilege) The reusable at standards@74d2f66 references no secrets: gitleaks runs as a checksum-verified binary, not gitleaks-action, so `secrets: inherit` only forwarded every repository and organisation secret to it (CWE-250, flagged by CodeRabbit and Hypatia WH008). The earlier comment calling it REQUIRED was copied from the reusable's own stale header note and is corrected here. actionlint clean. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0136eszqrQ53Kj7aBH1D4rXK --- .github/workflows/secret-scanner.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/secret-scanner.yml b/.github/workflows/secret-scanner.yml index f04a556..fa6eb1f 100644 --- a/.github/workflows/secret-scanner.yml +++ b/.github/workflows/secret-scanner.yml @@ -5,8 +5,9 @@ # shell-secrets). The job key MUST stay `scan`: the estate-wide # Secret-Scan-Floor ruleset requires the check context `scan / gitleaks`. # -# `secrets: inherit` is REQUIRED - without it the gitleaks action's inner -# secrets.GITHUB_TOKEN is empty and the scan silently degrades. +# No `secrets:` line, deliberately: the reusable references no secrets +# (gitleaks runs as a checksum-verified binary, not gitleaks-action), so +# `secrets: inherit` would only hand it every repo and org secret (CWE-250). name: Secret Scanner on: @@ -24,4 +25,3 @@ permissions: jobs: scan: uses: hyperpolymath/standards/.github/workflows/secret-scanner-reusable.yml@74d2f66f575246cf6e313ae7775f44df6e097ff2 - secrets: inherit