detect-secrets empêche les nouveaux secrets d'entrer dans votre code, sans vous obliger à nettoyer tout l'historique Git d'un coup. Grâce à un système de baseline versionnable, l'outil identifie les secrets existants et les met de côté pour se concentrer sur les ajouts. C'est l'approche pragmatique adoptée par Yelp pour sécuriser des centaines de dépôts en entreprise.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre la philosophie baseline de detect-secrets
- Scanner un projet et créer une baseline
- Auditer les résultats pour distinguer vrais et faux positifs
- Filtrer les faux positifs avec les exclusions et l'allowlist inline
- Intégrer detect-secrets comme pre-commit hook et en CI/CD
Le problème : des secrets qui s'accumulent dans l'historique
Section intitulée « Le problème : des secrets qui s'accumulent dans l'historique »Imaginez un dépôt Git avec 5 ans d'historique et 10 000 commits. Quelque part dans ces commits, des clés API et des mots de passe ont été commités par erreur. Les supprimer du code actuel ne suffit pas : ils restent dans l'historique Git. Et réécrire l'historique complet est souvent irréaliste.
C'est exactement ce problème que detect-secrets résout avec une approche différente des autres scanners :
| Approche | Comment ça marche | Limitation |
|---|---|---|
| Scanner tout l'historique (Gitleaks, TruffleHog) | Parcourt chaque commit | Lent sur les gros dépôts, beaucoup de bruit |
| Baseline (detect-secrets) | Photographie les secrets existants, bloque les nouveaux | Ne scanne pas l'historique |
L'idée est simple : on accepte que des secrets existent déjà (c'est la baseline), et on empêche la situation d'empirer. Ensuite, on migre les secrets existants progressivement.
Comment detect-secrets fonctionne
Section intitulée « Comment detect-secrets fonctionne »detect-secrets repose sur deux composants qui travaillent ensemble : les plugins et les filtres.
Les plugins trouvent les secrets dans le code. Il en existe trois types :
| Type | Fonctionnement | Exemple |
|---|---|---|
| Regex | Cherche des patterns structurés (clés AWS, tokens GitHub) | AKIA... détecté par AWSKeyDetector |
| Entropie | Mesure le "désordre" d'une chaîne (haute entropie = probable secret) | wJalrXUtnFEMI/K7MDENG détecté par Base64HighEntropyString |
| Mot-clé | Cherche des noms de variables associés aux secrets | password = "hunter2" détecté par KeywordDetector |
Les filtres éliminent les faux positifs. Par défaut, detect-secrets ignore :
- Les UUIDs (pattern reconnaissable)
- Les chaînes séquentielles (
abcdefg) - Les templates (
${SECRET},{{key}},<placeholder>) - Les fichiers de lock
- Les références indirectes (
password = get_secret())
Trois outils, trois usages
Section intitulée « Trois outils, trois usages »detect-secrets ne s'utilise pas comme un scanner unique lancé de temps en temps. L'outil expose trois commandes aux rôles bien séparés, et confondre scan et detect-secrets-hook est l'erreur d'installation la plus fréquente. scan écrit la baseline, il ne bloque rien et retourne toujours zéro. detect-secrets-hook compare les fichiers présentés à cette baseline et échoue en cas d'écart, c'est lui qui doit tourner en pre-commit et en CI. audit ne fait que qualifier des résultats déjà enregistrés.
| Commande | Quand l'utiliser |
|---|---|
detect-secrets scan | Créer ou mettre à jour la baseline |
detect-secrets-hook | Bloquer les commits contenant de nouveaux secrets |
detect-secrets audit | Analyser et labelliser les résultats de la baseline |
Installation
Section intitulée « Installation »detect-secrets est un paquet Python : il s'installe donc là où vous en avez besoin, sur votre poste pour l'usage quotidien et dans l'image du runner pour la CI. Choisissez l'onglet correspondant à votre situation. Les distributions récentes (Ubuntu 24.04, Debian 12, Fedora) appliquent la PEP 668 et refusent pip install en dehors d'un environnement virtuel : l'onglet venv est alors le seul qui fonctionne sans forcer. Les deux extras word_list et gibberish sont facultatifs et n'ont d'intérêt qu'une fois les faux positifs devenus gênants.
pip install detect-secretsPour les fonctionnalités optionnelles :
# Support word-list (exclure des mots connus)pip install detect-secrets[word_list]
# Support détecteur de gibberish (ML)pip install detect-secrets[gibberish]brew install detect-secretsSi votre système bloque l'installation globale (PEP 668) :
python3 -m venv .venvsource .venv/bin/activatepip install detect-secretsVérification :
detect-secrets --version# 1.5.0Scanner un projet et créer la baseline
Section intitulée « Scanner un projet et créer la baseline »La baseline est le fichier qui donne son sens à l'outil : elle enregistre l'état des secrets au moment où vous commencez, et tout ce qui apparaît ensuite est traité comme une régression. Deux points de vigilance dès cette première manipulation. La baseline se commite dans le dépôt, sans quoi le hook n'a aucune référence à comparer. Et elle ne contient jamais la valeur des secrets, uniquement une empreinte, le nom du fichier et le numéro de ligne : la publier ne divulgue rien, mais elle révèle où chercher, ce qui suffit à justifier de garder le dépôt privé.
-
Créer la baseline initiale : detect-secrets scanne tous les fichiers trackés par Git et génère un fichier JSON contenant les secrets détectés.
Fenêtre de terminal detect-secrets scan > .secrets.baselineLe fichier
.secrets.baselineest un JSON de cinq clés (version,plugins_used,filters_used,results,generated_at). Trois d'entre elles se relisent en revue :plugins_used: la liste des 27 plugins actifsfilters_used: les 11 filtres appliquésresults: les secrets détectés, regroupés par fichier
-
Vérifier ce qui a été détecté : utilisez la commande
audit --reportpour afficher un résumé lisible.Fenêtre de terminal detect-secrets audit .secrets.baseline --reportChaque secret est affiché avec son fichier, sa ligne, son type et sa catégorie (
UNVERIFIED,VERIFIED_TRUEouVERIFIED_FALSE). -
Versionner la baseline : ajoutez le fichier au dépôt Git. Il servira de référence pour bloquer les futurs secrets.
Fenêtre de terminal git add .secrets.baselinegit commit -m "chore: add detect-secrets baseline"
Mettre à jour la baseline
Section intitulée « Mettre à jour la baseline »Au fil du temps, votre code évolue. Des secrets sont supprimés, d'autres ajoutés. Pour synchroniser la baseline :
detect-secrets scan --baseline .secrets.baselineCette commande :
- Met à jour la baseline vers le format de la dernière version
- Ajoute les nouveaux secrets détectés
- Supprime les secrets qui ne sont plus dans le code
- Préserve les labels déjà attribués lors de l'audit
Scanner une chaîne individuelle
Section intitulée « Scanner une chaîne individuelle »Pour tester rapidement si une valeur est détectée comme secret :
detect-secrets scan --string "AKIAIOSFODNN7EXAMPLE"AWSKeyDetector : True (unverified)ArtifactoryDetector : FalseAzureStorageKeyDetector : FalseBase64HighEntropyString : False (3.684)BasicAuthDetector : False...Chaque plugin indique True ou False. Pour les détecteurs d'entropie, le score est affiché entre parenthèses (seuil par défaut : 4.5 pour base64, 3.0 pour hex).
Les 27 plugins intégrés
Section intitulée « Les 27 plugins intégrés »detect-secrets v1.5.0 embarque 27 plugins activés par défaut :
| Plugin | Ce qu'il détecte |
|---|---|
AWSKeyDetector | Clés d'accès AWS (AKIA...) |
AzureStorageKeyDetector | Clés de stockage Azure |
BasicAuthDetector | Identifiants en URLs (user:pass@host) |
GitHubTokenDetector | Tokens GitHub (ghp_, gho_, ghs_) |
GitLabTokenDetector | Tokens GitLab (glpat-) |
JwtTokenDetector | JSON Web Tokens (eyJ...) |
KeywordDetector | Variables nommées password, secret, token, etc. |
OpenAIDetector | Clés API OpenAI (sk-) |
PrivateKeyDetector | Clés privées RSA, DSA, ECDSA, OpenSSH |
SlackDetector | Tokens et webhooks Slack |
StripeDetector | Clés API Stripe (sk_live_, rk_live_) |
Base64HighEntropyString | Chaînes base64 à haute entropie (seuil : 4.5) |
HexHighEntropyString | Chaînes hexadécimales à haute entropie (seuil : 3.0) |
Et aussi : ArtifactoryDetector, CloudantDetector, DiscordBotTokenDetector, IbmCloudIamDetector, IbmCosHmacDetector, IPPublicDetector, MailchimpDetector, NpmDetector, PypiTokenDetector, SendGridDetector, SoftlayerDetector, SquareOAuthDetector, TelegramBotTokenDetector, TwilioKeyDetector.
Désactiver des plugins
Section intitulée « Désactiver des plugins »Tous les plugins ne sont pas pertinents partout. KeywordDetector déclenche sur toute variable nommée password ou token, y compris dans les jeux de tests et les fichiers d'exemple ; IPPublicDetector remonte les adresses IP publiques, dont celles, parfaitement légitimes, d'une documentation réseau. Désactiver un plugin change la composition de la baseline : régénérez-la dans la foulée, sinon le hook comparera des résultats produits par deux configurations différentes.
# Désactiver le détecteur de mots-clés et les IP publiquesdetect-secrets scan \ --disable-plugin KeywordDetector \ --disable-plugin IPPublicDetectorScanner avec un seul plugin
Section intitulée « Scanner avec un seul plugin »Pour n'utiliser qu'un seul plugin, désactivez tous les autres :
detect-secrets scan --list-all-plugins | \ grep -v 'AWSKeyDetector' | \ sed "s#^#--disable-plugin #g" | \ xargs detect-secrets scanRégler les seuils d'entropie
Section intitulée « Régler les seuils d'entropie »Les détecteurs d'entropie acceptent un seuil entre 0.0 et 8.0. Un seuil plus bas détecte plus de secrets (mais plus de faux positifs) :
# Seuil base64 abaissé de 4.5 à 3.5detect-secrets scan --base64-limit 3.5
# Seuil hex relevé de 3.0 à 4.0detect-secrets scan --hex-limit 4.0Gérer les faux positifs
Section intitulée « Gérer les faux positifs »Les faux positifs sont inévitables. detect-secrets propose plusieurs mécanismes pour les gérer.
Allowlist inline (pragma)
Section intitulée « Allowlist inline (pragma) »Ajoutez un commentaire pragma: allowlist secret sur la ligne à exclure :
# Ce n'est pas un vrai secret, c'est un exempleEXAMPLE_KEY = "AKIAIOSFODNN7EXAMPLE" # pragma: allowlist secretPour exclure la ligne suivante :
// pragma: allowlist nextline secretconst EXAMPLE_KEY = "AKIAIOSFODNN7EXAMPLE";Exclure des fichiers
Section intitulée « Exclure des fichiers »L'exclusion de fichiers travaille sur le chemin, pas sur le contenu. C'est le mécanisme à privilégier pour les répertoires de fixtures et les fichiers signés, dont on sait par construction qu'ils contiennent des chaînes à haute entropie. Le motif est une expression régulière Python appliquée au chemin relatif, \.signature$ ne correspond donc qu'aux fichiers se terminant par cette extension.
detect-secrets scan --exclude-files '\.signature$' --exclude-files 'test_data/.*'Exclure des lignes
Section intitulée « Exclure des lignes »L'exclusion par ligne est plus fine que l'exclusion par fichier : elle laisse le fichier sous surveillance et ne neutralise que les lignes reconnaissables. Réservez-la à des motifs vraiment discriminants, comme un préfixe de variable de démonstration. Un motif trop large, KEY par exemple, éteindrait silencieusement la détection sur la moitié du dépôt.
detect-secrets scan --exclude-lines 'EXAMPLE' --exclude-lines 'fake_secret'Exclure des valeurs de secrets
Section intitulée « Exclure des valeurs de secrets »Ce troisième niveau porte sur la valeur détectée elle-même, quel que soit le fichier ou la ligne où elle apparaît. C'est le bon outil pour les valeurs factices répétées dans tout le dépôt et pour les gabarits de variables non substituées. L'expression est une regex, d'où les échappements dans \$\{.*\} qui vise les placeholders de la forme ${VARIABLE}.
detect-secrets scan --exclude-secrets '(fakesecret|\$\{.*\})'Exclure avec une word-list
Section intitulée « Exclure avec une word-list »Pour exclure un grand nombre de faux positifs connus, utilisez un fichier de mots :
pip install detect-secrets[word_list]example-passwordtest-api-keySuperSecret123detect-secrets scan --word-list wordlist.txtAuditer la baseline
Section intitulée « Auditer la baseline »L'audit permet de labelliser chaque secret comme vrai positif ou faux positif. C'est utile pour :
- Établir la liste des secrets à migrer
- Mesurer la précision des plugins
- Améliorer la configuration
Audit interactif
Section intitulée « Audit interactif »L'audit ouvre une session en ligne de commande qui vous présente les résultats un par un, avec cinq lignes de contexte autour de chaque détection. Attention au sens de la question posée : detect-secrets demande « cette chaîne peut-elle être commitée ? », pas « est-ce un secret ? ». Répondre y marque donc un faux positif. Les réponses sont écrites dans la baseline sous forme de champ is_secret, et un q sauvegarde le travail déjà fait, ce qui permet de traiter un gros dépôt en plusieurs fois.
detect-secrets audit .secrets.baselinePour chaque secret, detect-secrets affiche le contexte (5 lignes avant/après) et demande :
Secret: 1 of 12Filename: config.envSecret Type: Secret Keyword----------1: DATABASE_HOST=localhost2: DATABASE_PORT=54323: DATABASE_USER=admin4: DATABASE_PASSWORD=SuperSecret123!5: AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE----------Should this string be committed to the repository? (y)es, (n)o, (s)kip, (q)uit:- y (yes) : c'est un faux positif, on peut le garder
- n (no) : c'est un vrai secret, à migrer
- s (skip) : on ne sait pas, on passe
- q (quit) : arrêter et sauvegarder
Générer un rapport
Section intitulée « Générer un rapport »Le mode --report produit une sortie lisible sans rien demander : c'est la forme à utiliser en revue d'équipe ou dans un job de CI qui publie un artefact. Les deux filtres --only-real et --only-false sont exclusifs et répondent à deux besoins différents. --only-real donne la liste de travail des secrets à faire tourner et à sortir du code ; --only-false sert à relire vos propres décisions, l'endroit où se cachent les erreurs d'audit qui rouvriront une brèche.
# Rapport completdetect-secrets audit --report .secrets.baseline
# Seulement les vrais secretsdetect-secrets audit --report --only-real .secrets.baseline
# Seulement les faux positifsdetect-secrets audit --report --only-false .secrets.baselineStatistiques de précision
Section intitulée « Statistiques de précision »Après un audit interactif, mesurez la précision de vos plugins :
detect-secrets audit --stats .secrets.baselineBase64HighEntropyString: - Precision: 75% (3 / 4 labelled secrets) - Recall: 60% (3 / 5 known true secrets)Comparer deux configurations
Section intitulée « Comparer deux configurations »La comparaison de deux baselines répond à une question précise : combien de détections gagne ou perd un changement de seuil ? Plutôt que de régler --base64-limit à l'intuition, produisez deux fichiers avec des seuils différents et laissez audit --diff afficher l'écart. Un seuil abaissé qui n'ajoute que du bruit se voit immédiatement, et vous conservez la trace de la décision.
detect-secrets scan --base64-limit 4 > limit4.jsondetect-secrets scan --base64-limit 5 > limit5.jsondetect-secrets audit --diff limit4.json limit5.jsonIntégration pre-commit
Section intitulée « Intégration pre-commit »La méthode recommandée par la documentation officielle est d'utiliser le framework pre-commit :
-
Créer la baseline :
Fenêtre de terminal detect-secrets scan > .secrets.baseline -
Configurer le hook dans
.pre-commit-config.yaml:.pre-commit-config.yaml repos:- repo: https://github.com/Yelp/detect-secretsrev: v1.5.0hooks:- id: detect-secretsargs: ['--baseline', '.secrets.baseline']exclude: package.lock.json -
Installer les hooks :
Fenêtre de terminal pre-commit install -
Tester : essayez de commiter un fichier contenant un secret non listé dans la baseline. Le commit sera bloqué.
Intégration CI/CD
Section intitulée « Intégration CI/CD »GitHub Actions
Section intitulée « GitHub Actions »Le job reproduit ce que fait le hook local, mais sur la totalité des fichiers suivis : detect-secrets scan --baseline réaligne la baseline sur le code, puis detect-secrets-hook échoue si une détection ne s'y trouve pas. Trois précautions de supply chain rendent ce workflow utilisable en l'état. permissions: {} au niveau du workflow retire tous les droits par défaut, le job ne réclamant ensuite que contents: read. L'action checkout est épinglée par SHA de commit (un tag comme @v4 peut être redéplacé) et reçoit persist-credentials: false pour ne pas laisser le jeton GitHub dans le runner. Enfin, la version de detect-secrets est figée : sans cela, une future version aux plugins différents ferait échouer le job sans qu'aucun code n'ait changé.
name: Detect Secretson: [push, pull_request]
permissions: {}
jobs: detect-secrets: runs-on: ubuntu-24.04 permissions: contents: read steps: - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - name: Install detect-secrets run: pip install detect-secrets==1.5.0 - name: Scan for secrets run: | detect-secrets scan --baseline .secrets.baseline git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baselineGitLab CI
Section intitulée « GitLab CI »Le pipeline GitLab suit la même logique, avec deux différences propres à la plateforme. L'image est épinglée par digest et non par tag : python:3.12-slim est réécrit à chaque publication d'un correctif Python, et un scanner de secrets qui change de base sans prévenir n'est plus reproductible. Récupérez le digest courant avec docker buildx imagetools inspect python:3.12-slim, puis mettez-le à jour sciemment. Le second point concerne git ls-files : il faut que le dépôt soit cloné avec son index Git, ce qui exclut les stratégies GIT_STRATEGY: none parfois utilisées pour accélérer les jobs.
detect-secrets: image: python:3.12-slim@sha256:57cd7c3a7a273101a6485ba99423ee568157882804b1124b4dd04266317710de stage: test before_script: - pip install detect-secrets==1.5.0 script: - detect-secrets scan --baseline .secrets.baseline - git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baselineUtilisation comme bibliothèque Python
Section intitulée « Utilisation comme bibliothèque Python »detect-secrets peut aussi être utilisé directement dans vos scripts Python :
from detect_secrets import SecretsCollectionfrom detect_secrets.settings import default_settings
secrets = SecretsCollection()with default_settings(): secrets.scan_file('config.env')
import jsonprint(json.dumps(secrets.json(), indent=2))Pour une configuration personnalisée :
from detect_secrets import SecretsCollectionfrom detect_secrets.settings import transient_settings
secrets = SecretsCollection()with transient_settings({ 'plugins_used': [ {'name': 'AWSKeyDetector'}, {'name': 'Base64HighEntropyString', 'limit': 5.0}, ],}) as settings: secrets.scan_file('config.env')detect-secrets vs Gitleaks vs TruffleHog
Section intitulée « detect-secrets vs Gitleaks vs TruffleHog »Les trois outils sont souvent présentés comme concurrents alors qu'ils ne répondent pas à la même question. Deux lignes du tableau suffisent à trancher. La ligne Historique Git dit si l'outil sait remonter dans les commits passés : c'est le seul critère qui compte pour un audit d'existant, et detect-secrets y répond non. La ligne Vérification des secrets dit si l'outil interroge le fournisseur pour savoir si la clé trouvée est encore active : c'est ce qui sépare une alerte à traiter aujourd'hui d'un token révoqué il y a deux ans, et c'est la force de TruffleHog. Le reste (langage, performance) pèse peu à l'échelle d'un dépôt d'équipe.
| Critère | detect-secrets | Gitleaks | TruffleHog |
|---|---|---|---|
| Langage | Python | Go | Go |
| Approche | Baseline + diff | Scan complet | Scan complet |
| Historique Git | Non (seulement les fichiers actuels) | Oui | Oui |
| Vérification des secrets | Oui (certains plugins) | Non | Oui (800+ détecteurs) |
| Plugins custom | Oui (fichiers Python) | Oui (règles TOML) | Non |
| Filtres custom | Oui (fichiers Python) | Oui (allowlists TOML) | Non |
| Audit interactif | Oui | Non | Non |
| Pre-commit | Oui (natif) | Oui | Oui |
| Performance | Rapide (pas d'historique) | Très rapide (Go) | Rapide (Go) |
| Cas d'usage idéal | Prévention progressive en entreprise | Scan complet d'historique | Scan multi-sources (Git, Docker, S3) |
Limites et pièges
Section intitulée « Limites et pièges »Ce tableau existe pour éviter le pire scénario : croire un dépôt propre parce que le pipeline est vert. La première ligne est la plus importante et découle directement du choix de conception de l'outil, detect-secrets ne regarde pas l'historique et ne détectera donc jamais une clé commitée l'an dernier puis retirée du code. Les deux lignes suivantes décrivent des angles morts de détection : un secret réparti sur plusieurs lignes, ou un mot de passe dont le nom de variable n'évoque rien pour le détecteur de mots-clés. Traitez la colonne Contournement comme une liste de tâches, pas comme une note de bas de page.
| Limitation | Conséquence | Contournement |
|---|---|---|
| Pas de scan d'historique | Les secrets déjà commités ne sont pas détectés | Utiliser Gitleaks ou TruffleHog en complément |
| Secrets multi-lignes | Non détectés par défaut | Écrire un plugin custom |
| Mots de passe faibles | login = "hunter2" passe si le KeywordDetector ne match pas le nom de variable | Combiner avec un mot-clé personnalisé |
| Maintenance de la baseline | Doit être mise à jour régulièrement | Automatiser avec detect-secrets scan --baseline |
| Pas de scan Docker/S3 | Limité aux fichiers locaux et Git | Utiliser TruffleHog pour ces cibles |
Dépannage
Section intitulée « Dépannage »Les cinq symptômes ci-dessous couvrent la mise en place initiale. Trois d'entre eux ont la même racine et méritent d'être reconnus d'un coup d'oeil : detect-secrets s'appuie sur Git pour savoir quels fichiers scanner. Une baseline vide, un dépôt non détecté ou un hook qui refuse de partir signalent presque toujours un fichier non ajouté à l'index plutôt qu'un défaut de l'outil. Commencez donc par git status avant de toucher aux seuils ou aux plugins.
| Symptôme | Cause | Solution |
|---|---|---|
Did not detect git repository | Version de Git < 1.8.5 | Mettre à jour Git |
Not a valid baseline file! (Windows) | Encodage du fichier incorrect | S'assurer que .secrets.baseline est en UTF-8 |
Baseline vide ("results": {}) | Les fichiers ne sont pas trackés par Git | Ajouter les fichiers avec git add ou utiliser --all-files |
Your baseline file is unstaged | .secrets.baseline pas dans la zone de staging | Exécuter git add .secrets.baseline |
| Trop de faux positifs | Seuils d'entropie trop bas ou plugins trop larges | Ajuster --base64-limit, --exclude-lines, ou --disable-plugin |
À retenir
Section intitulée « À retenir »- detect-secrets adopte une approche baseline : il accepte les secrets existants et empêche les nouveaux d'entrer.
- Le scan par défaut ne couvre que les fichiers trackés par Git (pas l'historique des commits).
- 27 plugins couvrent les principaux fournisseurs cloud, tokens, clés privées et mots de passe.
- Les filtres (exclusions, allowlist inline, word-list) permettent de gérer les faux positifs.
detect-secrets-hookest le gardien au quotidien : il bloque les commits contenant de nouveaux secrets.- L'audit interactif permet de labelliser les résultats et de mesurer la précision des plugins.
- Pour un scan d'historique complet, combinez avec Gitleaks ou TruffleHog.