fix(security): enable gitleaks default rules in .gitleaks.toml template (#1395)
Summary
.gitleaks.toml and the standards/gitleaks.toml template held only an [allowlist]. A file passed via --config replaces gitleaks' built-in ruleset, so the Secret scan (gitleaks) job loaded zero detection rules and passed on any history. This PR adds [extend] useDefault = true to both files, adds detection regression tests that run the real scanner, and documents the requirement.
Fixes #1395
How it was confirmed. Local gitleaks is v8.30.1, the same version ci.yml pins (.github/workflows/ci.yml secret-scan job; standards/workflows/ci.yml pins 8.30.1 too). I generated synthetic, obviously fake credentials at runtime (an AWS-access-key-shaped string and a ghp_-shaped string) and scanned them:
| Config | Result |
|---|---|
.gitleaks.toml (origin/main) | no leaks found, exit 0 |
standards/gitleaks.toml (origin/main) | no leaks found, exit 0 |
same file + [extend] useDefault = true | 3 findings (aws-access-token, github-pat, generic-api-key), exit 1 |
I got the same results with gitleaks dir, gitleaks detect --no-git, and git-history mode (gitleaks detect --source <repo>, the invocation CI uses).
Fix
.gitleaks.tomlandstandards/gitleaks.toml: add[extend] useDefault = true, with a comment saying it must not be removed. The_bmad/path allowlist from #996 is unchanged, so default rules plus that allowlist is the behavior #996 originally intended..github/workflows/ci.yml: comment only. TheRun gitleakscomment wrongly said--configexists to avoid the default ruleset. It now explains the allowlist and the mandatory extend block. The command is unchanged.standards/push-protection.md: the template block now includes the extend block, plus a paragraph explaining why it is mandatory.standards/workflows/ci.ymlis unchanged, because the root cause is the config file and not the job.
History check with default rules enabled. I ran gitleaks detect --source . --config .gitleaks.toml --redact --exit-code 1 over this repo's full history (all refs, 1,401 commits, including this branch) with the new config: no leaks found. Turning the rules on does not red main.
Regression tests (test/workflows/ci/secret-scan-config.bats, TDD: written first; on origin/main tests 4ā7 and 9 fail, and all pass with the fix)
- Both configs set
useDefault = trueinside[extend](static parse). - Both configs detect the synthetic secrets when
gitleaks detectruns in git-history mode against a throwaway repo. Assertions are on exit 1 plus theaws-access-tokenandgithub-patRuleIDs in the JSON report. - Control: an allowlist-only config detects nothing. This documents the failure mode and shows the tests can tell a working config from a zero-rule one.
ci-tests.ymlinstalls the same gitleaks version and checksum asci.yml, so the tests can't silently drift from the binary CI scans with.- Fixture values are put together at test time from split string pieces. No secret-shaped literal is committed, and the repo's own scan stays clean (confirmed by the history scan above).
- If gitleaks is missing, the tests fail with a message and are never skipped (AGENTS.md).
CI wiring: .github/workflows/ci-tests.yml now installs gitleaks v8.30.1 exactly the way ci.yml does: gh release download with a bounded retry loop and sha256sum -c against the same pinned checksum. Its paths: filters now include .gitleaks.toml and standards/gitleaks.toml.
Test commands
bats test/workflows/ci/: 21/21 okactionlint .github/workflows/ci.yml .github/workflows/ci-tests.yml: cleanshellcheck -s bash test/workflows/ci/secret-scan-config.bats: cleanmarkdownlint-cli2 standards/push-protection.md: 0 errors- Full-history
gitleaks detectwith the new config: no leaks found
Follow-ups / rollout (needs a human decision)
- Downstream repos are affected too. Every repo that copied the old
standards/gitleaks.toml(seeded byseed-repo-template.sh, which lives outside this repo) is also scanning with zero rules. This PR fixes the template only. Existing copies need a standards-sync pass, and those repos' histories have never been scanned with real rules. Turning the rules on may red theirSecret scan (gitleaks)required check until findings are triaged or rotated. I'd suggest runninggitleaks git --redactper repo before or alongside the sync. - No compliance check currently validates
.gitleaks.tomlcontents (scripts/lib/push-protection.shonly checks thatci.ymlinvokes gitleaks). A content check such asgitleaks_config_extends_defaultscould catch regressions fleet-wide. It is left out here because it would flag every existing repo at once, so it should be planned together with the sync above.
š¤ Generated with Claude Code
Problem
See the linked issue.
Risk
Medium ā changes GitHub Actions workflow behavior, which is exercised only post-merge; verify via the affected workflow runs.
Test plan
Tests added/updated: test/workflows/ci/secret-scan-config.bats. Verification: bash scripts/dev-lead-lint.sh (shellcheck --severity=warning) ran pre-commit; the bats suite runs in CI.
Rollback
Revert this PR. No non-revertible side effects (no tags, migrations, or external state).
Monitoring
Watch the affected workflow run(s) in the Actions tab and this PR's Lint check for regressions.