From d42e1364058f723e0ff39a88ffb6804cbd5c936e Mon Sep 17 00:00:00 2001 From: JCBauza <5790807+JCBauza@users.noreply.github.com> Date: Mon, 27 Apr 2026 01:41:58 +0000 Subject: [PATCH 1/4] feat(ci): add gitleaks PR-gating + base allowlist (Phase 0.B1-fleet) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds a Secret Scan workflow that runs gitleaks against every PR and push to default branch. Mirrors the canonical pattern in BfxLendingBot, BfxPingPongBot, and the Wave-1 repos (BotEventAggregator, Knowledge-Hub, DigiConta, blazor-shared, infra-iac). This is Wave 2 of the Phase 0.B1-fleet rollout — the 6 repos that didn't yet have a `gitleaks.toml`. CI-style scan (`--log-opts="--no-merges -1"`) on current HEAD reports `no leaks found` against gitleaks default rules, so the toml ships as a minimal scaffold (extend `paths` / add `regexes` if findings surface). Phase 0 of the Restart-2026-04 master plan requires zero secret-leak findings across all fleet repos before the bot fleet restarts on Opus 4.7. Pre-PR gating catches hardcoded secrets before they merge to master/main. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --- .github/workflows/secret-scan.yml | 40 +++++++++++++++++++++++++++++++ gitleaks.toml | 20 ++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 .github/workflows/secret-scan.yml create mode 100644 gitleaks.toml diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml new file mode 100644 index 0000000..31ef4b5 --- /dev/null +++ b/.github/workflows/secret-scan.yml @@ -0,0 +1,40 @@ +name: Secret Scan + +# Mirrors the BfxLendingBot / BfxPingPongBot pattern: +# Gitleaks PR-gating runs on every PR + every push to default branch +# to catch hardcoded secrets before merge. Uses repo-local gitleaks.toml +# for allowlist (extends gitleaks default rules with paths/regexes for +# this repo's known false positives). +# +# Phase 0.B1-fleet rollout (Restart-2026-04 master plan). + +on: + push: + branches: [master, main] + pull_request: + branches: [master, main] + workflow_dispatch: + +permissions: + contents: read + +concurrency: + group: secret-scan-${{ github.ref }} + cancel-in-progress: true + +jobs: + gitleaks: + name: Secret Scan + runs-on: [self-hosted, Linux, Build] + timeout-minutes: 5 + permissions: + contents: read + steps: + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Gitleaks — secret scanning + run: | + GITLEAKS_VERSION=$(curl -s https://api.github.com/repos/gitleaks/gitleaks/releases/latest | grep tag_name | cut -d '"' -f4 | sed 's/^v//') + mkdir -p "$HOME/.local/bin" + curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | tar xz -C "$HOME/.local/bin" gitleaks + "$HOME/.local/bin/gitleaks" detect --source . --config gitleaks.toml --log-opts="--no-merges -1" --verbose --redact --no-banner diff --git a/gitleaks.toml b/gitleaks.toml new file mode 100644 index 0000000..bc83a73 --- /dev/null +++ b/gitleaks.toml @@ -0,0 +1,20 @@ +# ============================================================================= +# Gitleaks Configuration +# ============================================================================= +# Mirrors the BfxLendingBot pattern: useDefault rules + minimal path +# allowlist. Currently no false positives on this repo's working tree; +# extend `paths` or add `regexes` here if findings surface in CI. +# ============================================================================= + +[extend] +useDefault = true + +[allowlist] + description = "Global allowlist" + paths = [ + # Standard ignores + '''\.gitleaksignore''', + '''\.env\.example''', + '''\.env\.local''', + ] + regexTarget = "line" From 7eb6f9f6eeaf21ec5bfa6bfdd420c3180a08a390 Mon Sep 17 00:00:00 2001 From: "cloudingenium-automation[bot]" <277329096+cloudingenium-automation[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 02:28:38 +0000 Subject: [PATCH 2/4] fix(ci): pin gitleaks version + scan PR range (Copilot review) Addresses Copilot's 3 template-level concerns on Wave 2 PRs: - Pin gitleaks to 8.30.1 + verify SHA256 (no latest-release scraping) - Scan full PR commit range on pull_request (was: --log-opts -1, missed earlier commits) - fetch-depth: 0 so the base..head range resolves --- .github/workflows/secret-scan.yml | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/.github/workflows/secret-scan.yml b/.github/workflows/secret-scan.yml index 31ef4b5..0e243ed 100644 --- a/.github/workflows/secret-scan.yml +++ b/.github/workflows/secret-scan.yml @@ -7,6 +7,10 @@ name: Secret Scan # this repo's known false positives). # # Phase 0.B1-fleet rollout (Restart-2026-04 master plan). +# Hardened 2026-04-27 per Copilot review (#9/#3/#10): +# - Pin gitleaks version + verify SHA256 (no latest-release scraping). +# - Scan full PR commit range, not just last commit (--log-opts -1). +# - Allowlist anchored regexes only (see gitleaks.toml). on: push: @@ -31,10 +35,26 @@ jobs: contents: read steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + # Full history needed so --log-opts can resolve the PR base..head range. + fetch-depth: 0 - name: Gitleaks — secret scanning + env: + GITLEAKS_VERSION: "8.30.1" + GITLEAKS_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb" run: | - GITLEAKS_VERSION=$(curl -s https://api.github.com/repos/gitleaks/gitleaks/releases/latest | grep tag_name | cut -d '"' -f4 | sed 's/^v//') mkdir -p "$HOME/.local/bin" - curl -sSfL "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | tar xz -C "$HOME/.local/bin" gitleaks - "$HOME/.local/bin/gitleaks" detect --source . --config gitleaks.toml --log-opts="--no-merges -1" --verbose --redact --no-banner + curl -sSfL -o /tmp/gitleaks.tar.gz \ + "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" + echo "${GITLEAKS_SHA256} /tmp/gitleaks.tar.gz" | sha256sum -c - + tar xzf /tmp/gitleaks.tar.gz -C "$HOME/.local/bin" gitleaks + + # Scan the full PR commit range on pull_request (catches secrets introduced + # earlier in the branch); fall back to the last push delta on direct pushes. + if [ "${{ github.event_name }}" = "pull_request" ]; then + LOG_OPTS="--log-opts=${{ github.event.pull_request.base.sha }}..${{ github.event.pull_request.head.sha }}" + else + LOG_OPTS="--log-opts=HEAD~1..HEAD" + fi + "$HOME/.local/bin/gitleaks" detect --source . --config gitleaks.toml "$LOG_OPTS" --verbose --redact --no-banner From 9514ce402517010477afa9d050b235978ab0692f Mon Sep 17 00:00:00 2001 From: "cloudingenium-automation[bot]" <277329096+cloudingenium-automation[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 02:28:41 +0000 Subject: [PATCH 3/4] fix(gitleaks): anchor allowlist regexes + drop .env.local (Copilot review) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Anchor paths so '.env.example.bak' and 'docs/.env.example.md' aren't allowlisted. - Remove .env.local — a real one with real secrets MUST trip the scan. Use .env.example for committed samples. --- gitleaks.toml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/gitleaks.toml b/gitleaks.toml index bc83a73..3610be0 100644 --- a/gitleaks.toml +++ b/gitleaks.toml @@ -4,6 +4,11 @@ # Mirrors the BfxLendingBot pattern: useDefault rules + minimal path # allowlist. Currently no false positives on this repo's working tree; # extend `paths` or add `regexes` here if findings surface in CI. +# +# Hardened 2026-04-27 per Copilot review: +# - Anchored regexes (no unintended matches like `foo/.env.local.backup`). +# - `.env.local` REMOVED from allowlist — a real `.env.local` with real +# secrets MUST trip gitleaks. Use `.env.example` for committed samples. # ============================================================================= [extend] @@ -12,9 +17,9 @@ useDefault = true [allowlist] description = "Global allowlist" paths = [ - # Standard ignores - '''\.gitleaksignore''', - '''\.env\.example''', - '''\.env\.local''', + # Anchored regexes — match exactly the intended file at repo root or any subdir, + # never a backup/sibling like `.env.example.bak` or `docs/.env.example.md`. + '''(^|/)\.gitleaksignore$''', + '''(^|/)\.env\.example$''', ] regexTarget = "line" From 0ad5ae454eb430ccee0974f8a63f42465f3fd25e Mon Sep 17 00:00:00 2001 From: "cloudingenium-automation[bot]" <277329096+cloudingenium-automation[bot]@users.noreply.github.com> Date: Mon, 27 Apr 2026 02:33:21 +0000 Subject: [PATCH 4/4] fix(ci): pin commitlint workflow actions to SHA (org ruleset) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Org ruleset enforces "all actions must be pinned to a full-length commit SHA". - actions/checkout@v4 → @de0fac2e... (v6.0.2) - wagoid/commitlint-github-action@v6 → @b948419d... (v6.2.1) Surfaced as a workflow setup error blocking the gitleaks Wave 2 PR; same fix should be applied fleet-wide to any other repo whose commitlint.yml still carries unpinned tags. --- .github/workflows/commitlint.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/commitlint.yml b/.github/workflows/commitlint.yml index 2f8dc7f..407b69c 100644 --- a/.github/workflows/commitlint.yml +++ b/.github/workflows/commitlint.yml @@ -8,13 +8,12 @@ jobs: commitlint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: Lint commits in PR - uses: wagoid/commitlint-github-action@v6 + uses: wagoid/commitlint-github-action@b948419dd99f3fd78a6548d48f94e3df7f6bf3ed # v6.2.1 with: configFile: ".commitlintrc.json" failOnWarnings: false firstParent: false -