Gitleaks — usage, précautions et dépannage CI¶
Guide pratique pour les dépôts DYNORS qui incluent le job gitleaks (template .gitlab/ci/gitleaks.template.yml + .gitleaks.toml). Complète le runbook technique dans le workspace dynors (copie / miroir selon organisation).
1. Ce que fait le job CI¶
| Contexte pipeline | Comportement Gitleaks | Intérêt |
|---|---|---|
| Merge request | gitleaks detect avec --log-opts "$CI_MERGE_REQUEST_DIFF_BASE_SHA..HEAD" |
Vérifie tous les commits de la MR par rapport à la branche cible. Un secret introduit puis « retiré » dans un commit ultérieur de la même MR peut encore être vu si Git expose le blob dans cette plage (selon l’historique). |
Push sur main / master (hors MR) |
gitleaks detect avec --no-git |
Ne scanne que l’arborescence checkoutée (fichiers tels qu’à HEAD). Évite d’échouer sur d’anciens commits encore présents dans un clone shallow alors que les fichiers actuels sont déjà corrigés. |
À retenir
Sur main, le CI ne « pardonne » pas l’historique : il impose que les fichiers présents dans le job ne contiennent pas de motifs interdits. Sur une MR, le périmètre est la plage de commits de la demande de fusion.
2. Précaution n°1 : la même version qu’en CI¶
L’image GitLab utilise zricethezav/gitleaks:v8.18.0. Une version locale plus récente (ex. Homebrew 8.30+) peut ne pas signaler ce que la CI signale, ou l’inverse selon l’évolution des règles par défaut (useDefault = true dans .gitleaks.toml).
Recommandation avant de pousser une doc sensible ou de clore un incident « Gitleaks » :
docker run --rm -v "$(pwd)":/repo -w /repo zricethezav/gitleaks:v8.18.0 \
detect --source=/repo --config=/repo/.gitleaks.toml --no-git -v
Pour une MR, rapprocher du mode CI (avec historique local complet) :
docker run --rm -v "$(pwd)":/repo -w /repo zricethezav/gitleaks:v8.18.0 \
detect --source=/repo --config=/repo/.gitleaks.toml \
--log-opts "<SHA_BASE>..HEAD" -v
Remplacez <SHA_BASE> par le commit de la branche cible (équivalent origin/main au moment de la branche).
3. Précautions rédaction (doc, exemples JSON, scripts)¶
3.1 Jetons GitLab (glpat-, gloas-, …)¶
La config DYNORS définit des règles du type glpat- + au moins 20 caractères alphanumériques / tirets. Donc :
- Interdit : coller un vrai PAT, même « pour un test rapide ».
- À éviter : tout pseudo-exemple où le préfixe
glpat-est suivi d’au moins 20 caractèresa-z,0-9,-,_— cela matche la règle même s’il est « bidon » (préférerglpat-EXAMPLE-DEMOouglpat-EXAMPLE). - Préférer : les formes explicitement allowlistées dans
.gitleaks.toml, par ex.glpat-EXAMPLE, ou une formulation sans préfixeglpat-(variable d’environnement décrite en texte : « coller le token créé dans GitLab »).
3.2 JWT et chaînes en base64¶
Toute chaîne qui ressemble à un JWT (eyJ…) ou à une clé API longue peut tomber dans generic-api-key (règles par défaut Gitleaks). En documentation :
- Utiliser un libellé du type
<JWT retourné par l’endpoint …>ou<jeton à coller depuis …>. - Éviter les faux JWT tronqués du type
eyJhbGciOiJIUzI1NiIs...dans des blocs copiables.
3.3 Faux positifs « métier »¶
Des identifiants d’exemple du type produit-order-00123 (lettres, tirets, chiffres) peuvent être classés generic-api-key selon la version et le contexte. Préférer des libellés clairement non secrets : exemple-ref-commande, REF-EXEMPLE, CMD-DEMO, etc.
3.4 Fichiers générés¶
Les dossiers build/, .gradle/, node_modules/, etc. sont en général exclus via [allowlist].paths du .gitleaks.toml. Ne pas committer de rapports gitleaks-report.json contenant des extraits sensibles.
4. Le pipeline échoue : diagnostic pas à pas¶
Étape A — Récupérer le rapport¶
Le job publie en échec un artifact gitleaks-report.json (JSON tableau de findings). Téléchargez-le depuis GitLab (job gitleaks → Browse / Télécharger).
Extraits utiles avec jq :
jq '.[] | {RuleID, File, StartLine, Secret: .Secret[0:40]}' gitleaks-report.json
jq '.[] | .Fingerprint' gitleaks-report.json
Étape B — Reproduire localement¶
- Se placer à la même révision que le pipeline (
CI_COMMIT_SHA). - Lancer Gitleaks en image
v8.18.0(voir section 2). - Si le job était une MR, utiliser
--log-optsavec la même base que GitLab ; simain, utiliser--no-git.
Étape C — Classifier la finding¶
| Nature | Action |
|---|---|
| Vrai secret (PAT, mot de passe, clé privée, token Vault prod) | Révoquer / faire tourner le secret côté fournisseur ; ne pas se contenter d’une entrée allowlist. Puis retirer toute trace du fichier ou réécrire l’historique si la politique sécu l’exige. |
| Faux positif documenté | Adapter le texte (préféré) ou, exceptionnellement, étendre [allowlist].regexes dans .gitleaks.toml avec un motif très étroit et un commentaire de justification. |
Secret uniquement dans l’historique (scan avec Git, pas --no-git) |
Rotation du secret ; ensuite git filter-repo / outil équivalent si la surface d’exposition impose de purger l’historique (coordination équipe). |
5. Exemples (cas fréquents)¶
Exemple 1 — « Ça passe chez moi, pas en CI »¶
- Cause typique : Gitleaks 8.30 en local vs 8.18 dans le runner.
- Action : reproduire avec Docker
v8.18.0; ajuster l’exemple dans la doc pour respecter les règles de cette version.
Exemple 2 — PAT dans un fichier Markdown¶
- Symptôme :
RuleID: gitlab-patougeneric-api-key, fichier*.md. - Action : remplacer par
glpat-EXAMPLEou texte sans token ; vérifier qu’aucun paragraphe ne cite un vraiglpat-…long.
Exemple 3 — MR verte mais plainte sur « historique »¶
- Le job MR scanne une plage de commits. Si un contributeur a ajouté un secret au commit
Aet l’a enlevé au commitB, la plage peut encore contenirA. - Action : interactive rebase / squash pour que le secret n’ait jamais existé dans la branche, ou ouvrir une nouvelle branche propre depuis
mainet cherry-pick proprement les bons commits.
Exemple 4 — main rouge après avoir « nettoyé » les fichiers¶
- Cause : CI en mode historique complet sur un clone qui inclut encore d’anciens commits avec blobs sensibles non présents à
HEAD. - Action côté infra : pour les dépôts concernés, le template peut utiliser
--no-gitsur les pipelines push hors MR (comportement dynors-core documenté dans le template). Les vrais secrets en tête de branche doivent quand même être corrigés.
6. Références internes¶
| Ressource | Emplacement |
|---|---|
| Runbook détaillé (hook, migration, scan historique) | Workspace dynors → docs/runbooks/gitleaks-secret-scanning.md |
| Config canonique | .gitleaks.toml à la racine de chaque sous-dépôt ; ne pas diverger sans revue sécu |
| Template CI | .gitlab/ci/gitleaks.template.yml (include local ou projet de templates) |
| Stratégie Vault, secrets CI & feuille de route | Vault, secrets CI & feuille de route |
| Règle / ADR secrets | Workspace → vault-secrets-dynors.mdc, docs/adr/ADR-2026-04-26-vault-strategie-completion.md |
7. Résumé « checklist » avant push¶
- [ ] Aucun
glpat-/gloas-/ … qui ressemble à un vrai jeton dans les fichiers suivis. - [ ] Exemples JWT / API : placeholders textuels, pas de préfixes
eyJen copier-coller. - [ ] Vérification locale avec
gitleaks:v8.18.0(Docker) alignée sur le mode du pipeline (--no-gitvs--log-opts). - [ ] En cas d’échec : télécharger
gitleaks-report.json, identifierRuleID+ fichier + ligne, corriger ou ouvrir un ticket sécu si fuite réelle.