job7 step C: gitleaks backstop — .gitleaks.toml, pre-commit hook, make scan-secrets

Pre-commit (lib/gitflow.sh emit-hook) now runs `gitleaks git --staged` right
after the root-commit/merge-in-progress guard, on ANY branch — not gated by
branch protection, since secrets shouldn't land anywhere. Non-blocking if
gitleaks isn't installed (warn + pass). gitleaks 8.30.1: `protect` isn't
listed in --help anymore (still runs, but undocumented) — used the
documented `git --staged` equivalent instead.

.gitleaks.toml allowlists the 3 false-positive classes from the job7 triage
(marketplace.json 40-hex "sha" fields, superpowers ws-protocol.test.js nonce,
git-game test-secret-* fixtures) plus a 4th entry for ~/.claude/.env itself —
not a false positive, but scanning our own canonical vault (BDR-026) is pure
noise for a tool meant to catch stray copies. All 4 verified empirically
against the real flagged files/values before being added, not assumed from
gitleaks' docs.

`make scan-secrets` scans this repo's git history + ~/.claude (dir scan),
redacted JSON to .audit/ (verified: --redact scrubs Match/Secret in the
report itself, not just console logs — safe to commit). Repo: 0 findings.
~/.claude: 18 remaining across 8 files — 5 match the known job7 triage
(pending the GO-gated purge in step D), 3 are new discoveries outside the
original triage scope (flagged for the user, not characterized further —
never read a flagged file's content past what gitleaks' redacted report
gives you).

lib/gitflow-test.sh T16: fake secret on a feature branch (not main/develop)
→ blocked, proving the check isn't gated by branch protection; clean commit
passes; PATH without gitleaks → warns and still commits. 96/96 green.
This commit is contained in:
Bastien Chanot
2026-07-07 12:47:06 +02:00
parent b9300c3382
commit 17bdd08b43
7 changed files with 493 additions and 14 deletions
+16 -1
View File
@@ -1,4 +1,4 @@
.PHONY: help install plugin link doctor update new-skill profile profile-list profile-current profile-reset onboard test
.PHONY: help install plugin link doctor update new-skill profile profile-list profile-current profile-reset onboard test scan-secrets
help: ## Show available commands
@grep -E '^[a-zA-Z_-]+:.*##' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*## "}; {printf " make %-14s %s\n", $$1, $$2}'
@@ -30,6 +30,21 @@ test: ## Run deterministic tests (lib/tests/*.test.sh + lib/gitflow-test.sh + li
*) bash "$$t" || fail=1 ;; \
esac; done; exit $$fail
scan-secrets: ## Gitleaks sweep: this repo's history + ~/.claude (job7 backstop). Extra repos: make scan-secrets repos="path1 path2"
@command -v gitleaks >/dev/null 2>&1 || { echo "gitleaks not installed — https://github.com/gitleaks/gitleaks"; exit 1; }
@mkdir -p .audit
@fail=0; \
echo "== this repo (git history) =="; \
gitleaks git . -c .gitleaks.toml --no-banner --redact -f json -r .audit/scan-secrets-repo.json || fail=1; \
echo "== ~/.claude (dir scan) =="; \
gitleaks dir "$$HOME/.claude" -c .gitleaks.toml --no-banner --redact -f json -r .audit/scan-secrets-claude-home.json || fail=1; \
for r in $(repos); do \
echo "== $$r (git history) =="; \
gitleaks git "$$r" -c .gitleaks.toml --no-banner --redact -f json -r ".audit/scan-secrets-$$(basename "$$r").json" || fail=1; \
done; \
echo "Reports: .audit/scan-secrets-*.json (already redacted — safe to inspect/commit)"; \
exit $$fail
profile: ## Run profile.sh (usage: make profile cmd="set design")
@bash lib/profile.sh $(cmd)