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
+33 -13
View File
@@ -48,22 +48,42 @@ manipuler une valeur de secret — edits sur les mécanismes seulement.
[A-Za-z_]*)=.*/\1=REDACTED/'`. `env VAR=x cmd` intact. Compound bail
(`;`/`&`/`||`) — jamais de pipe attaché au mauvais segment.
- [x] `lib/tests/rtk-rewrite.test.sh` — 3 cas + garde compound
- [ ] `make test` vert
- [ ] C. Backstop gitleaks (8.30.1 confirmé installé — `protect` non listé,
`gitleaks git --staged` = sous-commande documentée retenue)
- [ ] `.gitleaks.toml` racine — allowlist 3 classes (vérifiées empiriquement
contre les vrais fichiers : marketplace.json sha 40-hex, ws-protocol
nonce, test-secret-[0-9-]+)
- [ ] pre-commit gitflow (`lib/gitflow.sh` `_gitflow_emit_pre_commit`) —
- [x] `make test` vert (96/96 gitflow-test + suite complète)
- [x] C. Backstop gitleaks (8.30.1 confirmé installé — `protect` non listé
dans `--help` mais fonctionne encore ; `gitleaks git --staged` =
sous-commande documentée retenue à la place)
- [x] `.gitleaks.toml` racine — allowlist 3 classes job7 (vérifiées
empiriquement contre les vrais fichiers : marketplace.json sha
40-hex, ws-protocol nonce, test-secret-[0-9-]+) + 4e entrée
`(^|/)\.env$` (pas un faux positif — c'est le vault canonique
BDR-026 ; exclu du bruit, pas de la détection)
- [x] pre-commit gitflow (`lib/gitflow.sh` `_gitflow_emit_pre_commit`) —
`gitleaks git --staged` après guard root/merge, non-bloquant si absent
- [ ] `lib/gitflow-test.sh` — faux secret staged bloqué ; PATH sans gitleaks
→ warn + pass
- [ ] `make scan-secrets` — git × repos + dir ~/.claude, sortie → `.audit/`
- [ ] D. Purge (GO explicite par item)
- [ ] transcript 960bd2cf…jsonl — propose rm, attend GO
- [ ] `ide/27929.lock` stale — rm direct
- [x] `lib/gitflow-test.sh` T16 — faux secret (AKIA random) sur feature
branch → bloqué ; commit propre passe ; PATH sans gitleaks → warn
+ pass. 96/96 vert.
- [x] `make scan-secrets` — repo (git history) + dir ~/.claude, redacted
JSON → `.audit/` (`--redact` vérifié : Match/Secret redacted dans
le report, pas juste les logs). Repo : 0 (attendu). ~/.claude : 18
hits restants, 8 fichiers — voir D (5 déjà dans le triage job7,
3 NOUVEAUX non couverts par la spec initiale, à trancher)
- [ ] D. Purge (GO explicite par item) — état réel après `make scan-secrets` :
- [ ] transcript 960bd2cf…jsonl (generic-api-key) — propose rm, attend GO
- [x] `ide/27929.lock` — déjà rotée toute seule (fichier absent, session
finie). REMPLACÉE par `ide/20429.lock` (NOUVEAU, session active en
cours) — NE PAS rm (verrou live) ; candidat allowlist de classe
(`ide/*.lock` structurel, pas un secret) si le pattern se confirme
- [ ] `cleanupPeriodDays` — vérifier nom exact champ doc, proposer 7j, diff
settings avant écriture
- [ ] **NOUVEAU (hors spec initiale, découvert par `make scan-secrets`)** :
`paste-cache/7d48f52c7499c1a7.txt` (sourcegraph-access-token, 2) ;
transcript `f1c9c474-...jsonl` (generic-api-key, 8) — ni lus ni
caractérisés plus avant (règle job7 : jamais manipuler une valeur).
Décision utilisateur requise avant toute action.
- [x] **NOUVEAU (bruit, pas un item D)** : transcript de CETTE session
(`4b5c02a9-...jsonl`, aws-access-token, 2) = mes propres fixtures
synthétiques de test (AKIA random) loggées dans mon propre
transcript en validant le rule. Pas un vrai secret, rien à purger.
- [ ] Gate final : `make test` + `make scan-secrets` propre + table
étape/commit/gate + capitalize (BDR secrets-par-référence, MAJ BDR-026,
LRN piège `claude mcp add --env`)