Un couple d'AK/SK committé par erreur. Une clé API dans un fichier .env.example.
Un token GitLab dans les logs de CI. Ces scénarios ne sont pas hypothétiques :
GitGuardian a recensé 28,65 millions de nouveaux secrets en dur ajoutés sur
GitHub public en 2025, soit 34 % de plus qu'en 2024.
Le secrets scanning n'est pas une option. C'est une ligne de défense obligatoire dans toute usine logicielle.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Distinguer un vrai secret du bruit (hashes, UUID, fixtures de test)
- Placer les contrôles aux trois niveaux : pre-commit, merge request, branche
- Choisir entre GitLab Secret Detection, Gitleaks et TruffleHog
- Configurer une allowlist Gitleaks valide sans neutraliser le scanner
- Trier et remédier une alerte : qualification, rotation, traçabilité
Pourquoi le secrets scanning est non-négociable
Section intitulée « Pourquoi le secrets scanning est non-négociable »Le raisonnement tient en deux temps. D'abord, un secret ne fuit pas par accident mais par des chemins identifiables, donc instrumentables. Ensuite, l'objectif réaliste n'est pas d'empêcher toute fuite, mais de raccourcir le temps d'exposition entre le moment où le secret part et le moment où il est révoqué. Le même rapport GitGuardian mesure l'ampleur du problème inverse : en janvier 2026, 64 % des secrets valides détectés en 2022 étaient toujours actifs. Détecter ne sert à rien sans procédure de rotation.
Scénarios réalistes de fuite
Section intitulée « Scénarios réalistes de fuite »Les secrets fuient par des chemins prévisibles :
| Vecteur | Exemple | Détection possible |
|---|---|---|
| Commit direct | password = "admin123" dans le code | ✅ Scanning repo |
| Fichier exemple | .env.example avec vraies valeurs | ✅ Scanning repo |
| Historique Git | Secret supprimé mais présent dans l'historique | ✅ Scan historique |
| Logs CI/CD | Token affiché dans les logs de build | ⚠️ Masquage variables |
| Artefacts | Credentials dans un binaire ou config packagée | ⚠️ Scan artefacts |
| MR/PR | Secret dans une diff avant merge | ✅ Scan MR |
Objectif : réduire le temps d'exposition
Section intitulée « Objectif : réduire le temps d'exposition »L'enjeu n'est pas d'atteindre le "zéro secret exposé" (utopique), mais de :
- Détecter au plus tôt, Avant le merge, idéalement avant le push
- Standardiser la réponse, Procédure claire de rotation/révocation
- Tracer les incidents, Pour améliorer la prévention
Ce qu'on appelle "secret" (et ce qu'on n'appelle pas secret)
Section intitulée « Ce qu'on appelle "secret" (et ce qu'on n'appelle pas secret) »Définir le périmètre avant d'installer un scanner évite le scénario classique où l'équipe désactive l'outil au bout de deux semaines. Un scanner détecte des motifs, pas des secrets : c'est vous qui décidez ce qui compte comme credential exploitable et ce qui relève du bruit acceptable.
Typologie des secrets
Section intitulée « Typologie des secrets »Ces quatre familles se distinguent par leur procédure de rotation, pas par leur format. Un token API se révoque en une requête, une clé privée TLS impose de réémettre un certificat et de le redéployer, un mot de passe de base de données oblige à coordonner l'application et le service. Classer un secret dans la bonne famille dès la détection détermine donc le délai de remédiation à annoncer.
Tokens API
Credentials
Mots de passe, strings de connexion DB, credentials SMTP
Clés cryptographiques
Clés privées SSH/TLS, clés de chiffrement, JWT secrets
Webhooks & URLs
URLs avec tokens intégrés, webhooks Slack/Discord
Cas limites : le "bruit"
Section intitulée « Cas limites : le "bruit" »Tous les patterns détectés ne sont pas des secrets :
- UUIDs, Identifiants, pas des secrets
- Hashes, SHA256 d'un fichier, pas un mot de passe
- Fixtures de test, Fausses clés pour les tests unitaires
- Documentation, Exemples avec
xxxouREPLACE_ME
Une stratégie efficace gère ce bruit au lieu de le subir.
Où placer les contrôles (défense en profondeur)
Section intitulée « Où placer les contrôles (défense en profondeur) »La détection des secrets doit intervenir à plusieurs niveaux :
-
Avant le push (client-side)
Pre-commit hooks avec Gitleaks. Bloque le commit avant qu'il n'atteigne le serveur.
✅ Feedback immédiat pour le développeur ⚠️ Contournable (hooks désactivables)
-
Dans la Merge Request
Scan automatique sur chaque MR. Feedback visible dans la diff.
✅ Point de contrôle centralisé ✅ Impossible à contourner ⚠️ Détection "tardive" (après commit)
-
Sur la branche par défaut
Scan post-merge comme filet de sécurité.
✅ Couverture complète ⚠️ Réaction après le fait
Recommandation : combiner les trois niveaux. Le pre-commit accélère le feedback, la MR garantit le contrôle, le scan de branche assure la couverture.
Options d'implémentation
Section intitulée « Options d'implémentation »Trois outils dominent le terrain, et ils ne résolvent pas le même problème. La lecture utile du comparatif ci-dessous porte sur deux lignes seulement : Historique, qui décide si vous verrez les secrets déjà supprimés du code actuel, et Validation, qui décide du volume de faux positifs que votre équipe devra trier chaque semaine.
Comparatif des outils
Section intitulée « Comparatif des outils »Les trois colonnes ne s'excluent pas : beaucoup d'équipes font tourner Gitleaks en local et TruffleHog en CI. Retenez surtout la ligne Méthode, qui explique tout le reste. Une détection par expression régulière reconnaît les formats connus, rate un token maison et ne sait pas si le credential est encore actif. Une détection par entropie repère les chaînes aléatoires quel que soit leur format, au prix de faux positifs que la validation vient ensuite filtrer.
| Critère | GitLab Secret Detection | Gitleaks | TruffleHog |
|---|---|---|---|
| Intégration | Native GitLab | CI générique | CI générique |
| Méthode | Règles regex | Règles regex | Entropie + regex + validation |
| Historique | ⚠️ Limité | ✅ Complet | ✅ Complet |
| Validation | ❌ | ❌ | ✅ (certains providers) |
| Coût | Scanner inclus dans tous les tiers ; rapports MR et gestion des vulnérabilités en Ultimate | Gratuit | Gratuit / Enterprise |
| Bruit | Moyen | Configurable | Faible (validation) |
GitLab Secret Detection
Section intitulée « GitLab Secret Detection »Le scanner intégré à GitLab s'active par une seule ligne d'include, sans job à
écrire. Il tourne sur tous les tiers, y compris Free ; en Free et Premium
vous récupérez le rapport JSON en artefact, alors qu'Ultimate l'intègre au
widget de la merge request, au tableau de bord sécurité et aux politiques de
sécurité. Son angle mort est l'historique : le scan porte sur les commits de la
branche courante, pas sur l'intégralité du dépôt.
include: - template: Jobs/Secret-Detection.gitlab-ci.yml- Génère un rapport de sécurité consultable dans la MR (tier Ultimate)
- Règles maintenues par GitLab
- Limité aux commits de la branche courante (pas l'historique complet)
→ Documentation GitLab Secret Detection
Gitleaks
Section intitulée « Gitleaks »Gitleaks est un binaire Go unique, sans dépendance, qui s'insère dans n'importe
quelle CI. Depuis la version 8, la commande detect a disparu au profit de deux
sous-commandes explicites : gitleaks git parcourt l'historique des commits,
gitleaks dir inspecte l'arborescence de fichiers telle qu'elle est sur le
disque. L'image est épinglée par digest ci-dessous pour que la pipeline
exécute exactement le binaire audité, et non ce que le registre publiera demain
sous le même tag.
secrets-scan: image: ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f script: - gitleaks git --redact --verbose . rules: - if: $CI_PIPELINE_SOURCE == "merge_request_event"Forces :
- Configuration fine via
.gitleaks.toml - Scan de l'historique complet (
gitleaks git --log-opts="--all" .) - Code de sortie 1 dès qu'une fuite est trouvée, exploitable pour le gating
TruffleHog
Section intitulée « TruffleHog »TruffleHog se distingue par la vérification active : pour les fournisseurs
qu'il connaît, il appelle l'API concernée pour savoir si le credential trouvé
fonctionne encore. Un secret déjà révoqué sort du rapport, ce qui fait chuter le
volume de tri. Le filtre --results=verified remplace l'ancien
--only-verified, toujours accepté mais retiré de l'aide. Attention au détail
qui coûte des heures de débogage en CI : avec --fail, TruffleHog sort avec le
code 183, pas 1, ce qui déroute les scripts qui testent -eq 1.
secrets-scan: image: trufflesecurity/trufflehog:3.95.9@sha256:59b244249d1a1aef4baa24fe73d3c931616264482580d806d77f6c74d26b3e42 script: - trufflehog git file://. --results=verified --failForces :
- Vérifie si le secret est encore valide (certains providers)
- Réduit drastiquement les faux positifs
- Scan multi-sources (Git, S3, Slack, etc.)
Critères de choix
Section intitulée « Critères de choix »Ce tableau se lit par la colonne de gauche : identifiez la ligne qui décrit votre situation actuelle, pas celle que vous visez dans six mois. La dernière ligne est celle que je recommande dès que l'équipe dépasse une dizaine de développeurs, parce qu'elle place un contrôle rapide et local avant le push et un contrôle exhaustif et non contournable dans la CI.
| Situation | Recommandation |
|---|---|
| GitLab Ultimate, équipe petite | GitLab Secret Detection |
| CI générique, besoin de contrôle | Gitleaks |
| Volume important, faux positifs problématiques | TruffleHog |
| Défense en profondeur | Gitleaks (pre-commit) + TruffleHog (CI) |
Décisions de gouvernance
Section intitulée « Décisions de gouvernance »Avant d'implémenter, l'équipe doit trancher :
Règles de blocage
Section intitulée « Règles de blocage »Ces trois questions déterminent si votre scanner sera respecté ou contourné.
Bloquer une pipeline coûte du temps à toute l'équipe : la décision doit être
prise avant le déploiement, pas au premier incident. La troisième ligne est
la plus souvent négligée alors qu'elle conditionne les deux autres, car une
règle de blocage sans mécanisme d'exception documenté finit toujours en
--no-verify généralisé.
| Question | Options |
|---|---|
| Quand bloquer la pipeline ? | Toujours / Seulement sur branches protégées / Jamais (warning) |
| Quels types de secrets bloquent ? | Tous / Seulement haute sévérité / Liste explicite |
| Quid des faux positifs ? | Baseline + allowlist / Review manuelle |
Ownership et escalade
Section intitulée « Ownership et escalade »Une alerte sans propriétaire nommé reste ouverte. Répondez aux trois questions ci-dessous par écrit, dans le dépôt lui-même, avant d'activer le scanner : c'est ce document que la personne d'astreinte ouvrira à 2 h du matin. Le choix le plus efficace en pratique consiste à confier le traitement à l'auteur du commit, qui seul sait à quoi sert le credential, avec l'équipe sécurité en escalade sur les secrets de production.
- Qui traite une alerte ?, L'auteur du commit ? L'équipe sécurité ?
- Quel délai de traitement ?, Immédiat pour les vrais secrets ?
- Quelle escalade ?, Notification Slack ? Incident automatique ?
Gestion des exceptions
Section intitulée « Gestion des exceptions »Les exceptions sont inévitables. Les documenter :
[extend]useDefault = true
[[allowlists]]description = "Fausses cles utilisees par les tests unitaires"regexes = ['''FAKE_.*_KEY''']paths = ['''tests/''', '''fixtures/''']Le bloc [extend] avec useDefault = true est obligatoire : sans lui, votre
fichier remplace le jeu de règles par défaut de Gitleaks au lieu de le
compléter, et le scanner ne détecte plus rien. Les exclusions globales
s'écrivent avec [[allowlists]] au niveau racine ; la forme [[rules.allowlist]]
que l'on croise encore dans de vieux exemples fait échouer le chargement de la
configuration avec le message 'Rules[0].AllowList' expected a map, got 'slice'.
Vérifiez toujours qu'une modification du fichier laisse le scanner opérationnel,
en réintroduisant volontairement un faux secret dans une branche de test.
Règles :
- Toute exception a une date d'expiration
- Toute exception est justifiée (commentaire)
- Revue trimestrielle des exceptions
Processus de triage et remédiation
Section intitulée « Processus de triage et remédiation »Un scanner qui remonte des alertes que personne ne traite dégrade la sécurité, parce qu'il installe l'habitude d'ignorer les avertissements. Le processus ci-dessous se déroule dans un ordre imposé : on qualifie avant d'agir, puis on applique l'action minimale correspondant à la situation, puis on trace. La question qui gouverne tout le reste vient en deuxième position, l'exposition publique, car c'est elle qui transforme un incident interne en course contre les robots de scraping.
Qualifier l'alerte
Section intitulée « Qualifier l'alerte »-
Vrai secret ?
Faux positif (hash, fixture, exemple) → Ajouter à l'allowlist
-
Exposé publiquement ?
Repo public, MR publique, historique accessible → Rotation urgente
-
Quel scope ?
Accès limité (dev) vs accès large (prod, admin)
-
Rotation possible ?
Token révocable → Révoquer immédiatement Credential hardcodé → Rotation + audit d'utilisation
Actions minimales
Section intitulée « Actions minimales »Le mot « minimales » est à prendre au pied de la lettre : ce sont les actions en dessous desquelles l'incident n'est pas clos. Notez que la rotation est présente dans les trois lignes, y compris quand le secret a été retiré du code. La raison tient au fonctionnement de Git : un commit supprimé de la branche reste accessible dans les objets du dépôt, dans les forks et dans les clones déjà réalisés. Seule la révocation du credential ferme réellement l'accès.
| Situation | Action |
|---|---|
| Secret valide détecté | 1. Révoquer/rotater 2. Vérifier les logs d'accès 3. Supprimer du code |
| Secret dans l'historique | Rotation obligatoire (même si supprimé du code actuel) |
| Secret exposé publiquement | Rotation + audit + évaluer la purge d'historique |
Traçabilité
Section intitulée « Traçabilité »Chaque incident de secret exposé devrait générer :
- Une issue de suivi (rotation effectuée ?)
- Un post-mortem léger (comment c'est arrivé ?)
- Une amélioration (règle ajoutée, process modifié)
Erreurs fréquentes
Section intitulée « Erreurs fréquentes »Ces six croyances reviennent dans presque tous les audits de pipeline. Les trois premières portent sur une compréhension incomplète du fonctionnement de Git et de la CI, les trois dernières sur des choix d'organisation qui font échouer un dispositif pourtant correctement outillé. La dernière est la plus structurante : confondre détection et gestion des secrets conduit à empiler des scanners sans jamais régler la cause.
❌ On a masqué la variable, donc c'est bon
❌ On a supprimé le fichier du repo
git log -p ou un clone suffisent à retrouver le secret.
Seule la rotation protège. ❌ On scanne la branche default, ça suffit
❌ Trop de faux positifs → on désactive
❌ On bloque tout dès J1
❌ Confondre scanning et management
Checklist
Section intitulée « Checklist »La checklist suit les trois temps d'un déploiement : ce qu'on décide avant d'écrire la moindre ligne de CI, ce qu'on installe, puis ce qu'on doit avoir prêt le jour où une alerte tombe. Traitez-les dans cet ordre, un dispositif technique posé sans décision de gouvernance produit surtout du contournement.
Design (décisions)
Section intitulée « Design (décisions) »Ces cinq points se tranchent en réunion, pas dans un fichier YAML. Tant qu'ils ne sont pas écrits quelque part dans le dépôt, chaque alerte relancera la même discussion. Le point le plus discuté est le troisième, les règles de blocage : commencez en mode avertissement, mesurez le volume réel de détections sur un mois, puis durcissez.
- Niveaux de scan définis (pre-commit / MR / branche)
- Outil(s) choisi(s) avec justification
- Règles de blocage documentées
- Ownership des alertes assigné
- Process d'exception défini
Implémentation (contrôles)
Section intitulée « Implémentation (contrôles) »Le seul point réellement obligatoire de cette liste est le job CI sur les
merge requests : c'est le seul contrôle qu'un développeur ne peut pas
désactiver depuis son poste. Le hook pre-commit améliore le confort et raccourcit
la boucle de retour, mais il se contourne avec git commit --no-verify et ne
doit jamais être compté comme une barrière. L'allowlist initiale se remplit en
faisant tourner le scanner une première fois sur l'historique, avant d'activer
le blocage.
- Pre-commit hooks configurés (optionnel mais recommandé)
- Job CI de scan sur les MR
- Scan de la branche default comme filet
- Allowlist initiale pour les faux positifs connus
- Notifications configurées (Slack, email)
Run (remédiation)
Section intitulée « Run (remédiation) »C'est la partie que les équipes préparent en dernier et dont elles ont besoin en premier. Une procédure de rotation par type de secret est indispensable parce que révoquer un token GitHub et faire tourner un mot de passe de base de données n'engagent ni les mêmes commandes, ni les mêmes personnes, ni le même risque d'interruption de service. Rédigez-les à froid, avec la commande exacte et le nom du service concerné.
- Procédure de rotation documentée par type de secret
- Contacts d'escalade identifiés
- Template d'issue pour les incidents secrets
- Revue trimestrielle des exceptions planifiée
À retenir
Section intitulée « À retenir »- Un secret committé est compromis, même supprimé du code : l'historique Git, les forks et les clones le conservent. Seule la rotation ferme l'accès.
- Placez le contrôle à trois niveaux : pre-commit pour le confort, merge request pour la barrière non contournable, branche par défaut comme filet.
- Gitleaks 8 n'a plus de commande
detect: utilisezgitleaks gitpour l'historique,gitleaks dirpour l'arborescence. - TruffleHog valide les secrets auprès des fournisseurs et sort avec le code
183 quand
--failest actif, pas avec 1. - Épinglez les images de scanner par digest : un scanner qui change sous vos pieds fausse la comparaison entre deux exécutions.
- Décidez de la gouvernance (blocage, ownership, exceptions) avant de déployer l'outil, sinon vous obtiendrez du contournement plutôt que des corrections.