Aller au contenu
Sécurité medium

detect-secrets : empêcher les secrets d'entrer dans votre code

16 min de lecture

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.

  • 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 :

ApprocheComment ça marcheLimitation
Scanner tout l’historique (Gitleaks, TruffleHog)Parcourt chaque commitLent sur les gros dépôts, beaucoup de bruit
Baseline (detect-secrets)Photographie les secrets existants, bloque les nouveauxNe 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.

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 :

TypeFonctionnementExemple
RegexCherche des patterns structurés (clés AWS, tokens GitHub)AKIA... détecté par AWSKeyDetector
EntropieMesure 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 secretspassword = "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())

detect-secrets fournit trois commandes distinctes :

CommandeQuand l’utiliser
detect-secrets scanCréer ou mettre à jour la baseline
detect-secrets-hookBloquer les commits contenant de nouveaux secrets
detect-secrets auditAnalyser et labelliser les résultats de la baseline
Fenêtre de terminal
pip install detect-secrets

Pour les fonctionnalités optionnelles :

Fenêtre de terminal
# Support word-list (exclure des mots connus)
pip install detect-secrets[word_list]
# Support détecteur de gibberish (ML)
pip install detect-secrets[gibberish]

Vérification :

Fenêtre de terminal
detect-secrets --version
# 1.5.0
  1. 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.baseline

    Le fichier .secrets.baseline contient trois sections :

    • plugins_used : la liste des 27 plugins actifs
    • filters_used : les 11 filtres appliqués
    • results : les secrets détectés, regroupés par fichier
  2. Vérifier ce qui a été détecté : utilisez la commande audit --report pour afficher un résumé lisible.

    Fenêtre de terminal
    detect-secrets audit .secrets.baseline --report

    Chaque secret est affiché avec son fichier, sa ligne, son type et sa catégorie (UNVERIFIED, VERIFIED_TRUE ou VERIFIED_FALSE).

  3. 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.baseline
    git commit -m "chore: add detect-secrets baseline"

Au fil du temps, votre code évolue. Des secrets sont supprimés, d’autres ajoutés. Pour synchroniser la baseline :

Fenêtre de terminal
detect-secrets scan --baseline .secrets.baseline

Cette 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

Pour tester rapidement si une valeur est détectée comme secret :

Fenêtre de terminal
detect-secrets scan --string "AKIAIOSFODNN7EXAMPLE"
AWSKeyDetector : True (unverified)
ArtifactoryDetector : False
AzureStorageKeyDetector : False
Base64HighEntropyString : 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).

detect-secrets v1.5.0 embarque 27 plugins activés par défaut :

PluginCe qu’il détecte
AWSKeyDetectorClés d’accès AWS (AKIA...)
AzureStorageKeyDetectorClés de stockage Azure
BasicAuthDetectorIdentifiants en URLs (user:pass@host)
GitHubTokenDetectorTokens GitHub (ghp_, gho_, ghs_)
GitLabTokenDetectorTokens GitLab (glpat-)
JwtTokenDetectorJSON Web Tokens (eyJ...)
KeywordDetectorVariables nommées password, secret, token, etc.
OpenAIDetectorClés API OpenAI (sk-)
PrivateKeyDetectorClés privées RSA, DSA, ECDSA, OpenSSH
SlackDetectorTokens et webhooks Slack
StripeDetectorClés API Stripe (sk_live_, rk_live_)
Base64HighEntropyStringChaînes base64 à haute entropie (seuil : 4.5)
HexHighEntropyStringChaînes hexadécimales à haute entropie (seuil : 3.0)

Et aussi : ArtifactoryDetector, CloudantDetector, DiscordBotTokenDetector, IbmCloudIamDetector, IbmCosHmacDetector, IPPublicDetector, MailchimpDetector, NpmDetector, PypiTokenDetector, SendGridDetector, SoftlayerDetector, SquareOAuthDetector, TelegramBotTokenDetector, TwilioKeyDetector.

Pour réduire le bruit, désactivez les plugins inutiles :

Fenêtre de terminal
# Désactiver le détecteur de mots-clés et les IP publiques
detect-secrets scan \
--disable-plugin KeywordDetector \
--disable-plugin IPPublicDetector

Pour n’utiliser qu’un seul plugin, désactivez tous les autres :

Fenêtre de terminal
detect-secrets scan --list-all-plugins | \
grep -v 'AWSKeyDetector' | \
sed "s#^#--disable-plugin #g" | \
xargs detect-secrets scan

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) :

Fenêtre de terminal
# Seuil base64 abaissé de 4.5 à 3.5
detect-secrets scan --base64-limit 3.5
# Seuil hex relevé de 3.0 à 4.0
detect-secrets scan --hex-limit 4.0

Les faux positifs sont inévitables. detect-secrets propose plusieurs mécanismes pour les gérer.

Ajoutez un commentaire pragma: allowlist secret sur la ligne à exclure :

# Ce n'est pas un vrai secret, c'est un exemple
EXAMPLE_KEY = "AKIAIOSFODNN7EXAMPLE" # pragma: allowlist secret

Pour exclure la ligne suivante :

// pragma: allowlist nextline secret
const EXAMPLE_KEY = "AKIAIOSFODNN7EXAMPLE";

Ignorez des fichiers par regex :

Fenêtre de terminal
detect-secrets scan --exclude-files '\.signature$' --exclude-files 'test_data/.*'

Ignorez des lignes qui correspondent à un pattern :

Fenêtre de terminal
detect-secrets scan --exclude-lines 'EXAMPLE' --exclude-lines 'fake_secret'

Ignorez des secrets par leur valeur :

Fenêtre de terminal
detect-secrets scan --exclude-secrets '(fakesecret|\$\{.*\})'

Pour exclure un grand nombre de faux positifs connus, utilisez un fichier de mots :

Fenêtre de terminal
pip install detect-secrets[word_list]
wordlist.txt
example-password
test-api-key
SuperSecret123
Fenêtre de terminal
detect-secrets scan --word-list wordlist.txt

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
Fenêtre de terminal
detect-secrets audit .secrets.baseline

Pour chaque secret, detect-secrets affiche le contexte (5 lignes avant/après) et demande :

Secret: 1 of 12
Filename: config.env
Secret Type: Secret Keyword
----------
1: DATABASE_HOST=localhost
2: DATABASE_PORT=5432
3: DATABASE_USER=admin
4: 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
Fenêtre de terminal
# Rapport complet
detect-secrets audit --report .secrets.baseline
# Seulement les vrais secrets
detect-secrets audit --report --only-real .secrets.baseline
# Seulement les faux positifs
detect-secrets audit --report --only-false .secrets.baseline

Après un audit interactif, mesurez la précision de vos plugins :

Fenêtre de terminal
detect-secrets audit --stats .secrets.baseline
Base64HighEntropyString:
- Precision: 75% (3 / 4 labelled secrets)
- Recall: 60% (3 / 5 known true secrets)

Pour optimiser vos réglages, comparez deux baselines :

Fenêtre de terminal
detect-secrets scan --base64-limit 4 > limit4.json
detect-secrets scan --base64-limit 5 > limit5.json
detect-secrets audit --diff limit4.json limit5.json

La méthode recommandée par la documentation officielle est d’utiliser le framework pre-commit :

  1. Créer la baseline :

    Fenêtre de terminal
    detect-secrets scan > .secrets.baseline
  2. Configurer le hook dans .pre-commit-config.yaml :

    .pre-commit-config.yaml
    repos:
    - repo: https://github.com/Yelp/detect-secrets
    rev: v1.5.0
    hooks:
    - id: detect-secrets
    args: ['--baseline', '.secrets.baseline']
    exclude: package.lock.json
  3. Installer les hooks :

    Fenêtre de terminal
    pre-commit install
  4. Tester : essayez de commiter un fichier contenant un secret non listé dans la baseline. Le commit sera bloqué.

.github/workflows/detect-secrets.yml
name: Detect Secrets
on: [push, pull_request]
jobs:
detect-secrets:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Install detect-secrets
run: pip install detect-secrets
- name: Scan for secrets
run: |
detect-secrets scan --baseline .secrets.baseline
git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline
.gitlab-ci.yml
detect-secrets:
image: python:3.12-slim
stage: test
before_script:
- pip install detect-secrets
script:
- detect-secrets scan --baseline .secrets.baseline
- git ls-files -z | xargs -0 detect-secrets-hook --baseline .secrets.baseline

detect-secrets peut aussi être utilisé directement dans vos scripts Python :

from detect_secrets import SecretsCollection
from detect_secrets.settings import default_settings
secrets = SecretsCollection()
with default_settings():
secrets.scan_file('config.env')
import json
print(json.dumps(secrets.json(), indent=2))

Pour une configuration personnalisée :

from detect_secrets import SecretsCollection
from 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')
Critèredetect-secretsGitleaksTruffleHog
LangagePythonGoGo
ApprocheBaseline + diffScan completScan complet
Historique GitNon (seulement les fichiers actuels)OuiOui
Vérification des secretsOui (certains plugins)NonOui (800+ détecteurs)
Plugins customOui (fichiers Python)Oui (règles TOML)Non
Filtres customOui (fichiers Python)Oui (allowlists TOML)Non
Audit interactifOuiNonNon
Pre-commitOui (natif)OuiOui
PerformanceRapide (pas d’historique)Très rapide (Go)Rapide (Go)
Cas d’usage idéalPrévention progressive en entrepriseScan complet d’historiqueScan multi-sources (Git, Docker, S3)
LimitationConséquenceContournement
Pas de scan d’historiqueLes secrets déjà commités ne sont pas détectésUtiliser Gitleaks ou TruffleHog en complément
Secrets multi-lignesNon détectés par défautÉcrire un plugin custom
Mots de passe faibleslogin = "hunter2" passe si le KeywordDetector ne match pas le nom de variableCombiner avec un mot-clé personnalisé
Maintenance de la baselineDoit être mise à jour régulièrementAutomatiser avec detect-secrets scan --baseline
Pas de scan Docker/S3Limité aux fichiers locaux et GitUtiliser TruffleHog pour ces cibles
SymptômeCauseSolution
Did not detect git repositoryVersion de Git < 1.8.5Mettre à jour Git
Not a valid baseline file! (Windows)Encodage du fichier incorrectS’assurer que .secrets.baseline est en UTF-8
Baseline vide ("results": {})Les fichiers ne sont pas trackés par GitAjouter les fichiers avec git add ou utiliser --all-files
Your baseline file is unstaged.secrets.baseline pas dans la zone de stagingExécuter git add .secrets.baseline
Trop de faux positifsSeuils d’entropie trop bas ou plugins trop largesAjuster --base64-limit, --exclude-lines, ou --disable-plugin
  • 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-hook est 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.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn