
Gitleaks détecte les secrets exposés dans vos dépôts Git, fichiers et archives. Rapide et hautement configurable, c'est l'outil de référence pour les pre-commit hooks et les pipelines CI/CD. Avec plus de 150 règles intégrées, il identifie les clés AWS, tokens GitHub, Stripe, Slack et bien d'autres.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Comprendre comment Gitleaks détecte les secrets avec des règles regex
- Scanner différentes sources : dépôts Git, fichiers, archives, entrée standard
- Configurer des règles personnalisées et des exclusions
- Intégrer Gitleaks dans vos pipelines CI/CD (GitHub Actions, GitLab CI)
- Utiliser les fonctionnalités avancées : décodage, archives, baseline
Le problème des secrets dans le code
Section intitulée « Le problème des secrets dans le code »Un secret poussé sur un dépôt public ne reste pas confidentiel le temps que vous vous en aperceviez. Des robots d'indexation surveillent en continu les évènements publics de GitHub et testent les identifiants trouvés, souvent avant même que l'auteur du commit ait fini sa journée. GitHub a d'ailleurs industrialisé la réponse avec le secret scanning et des partenariats de révocation automatique avec les fournisseurs cloud, ce qui en dit long sur la fréquence du phénomène.
Les secrets se retrouvent exposés pour plusieurs raisons :
| Situation | Exemple | Risque |
|---|---|---|
| Fichier de config commité | .env oublié dans .gitignore | Clés API en clair dans l'historique Git |
| Mot de passe hardcodé | password = "admin123" dans le code | Accès à la base de données |
| Token dans les logs | Authorization: Bearer sk_live_... | Compromission de compte |
| Secret encodé en base64 | YXdzX3NlY3JldF9hY2Nlc3Nfa2V5... | Fausse impression de sécurité |
| Historique Git | Secret supprimé mais présent dans un ancien commit | Reste accessible via git log |
Le problème : même si vous supprimez un secret, il reste dans l'historique Git. Et les scanners malveillants analysent tout l'historique, pas juste la branche principale.
Comment Gitleaks résout ce problème
Section intitulée « Comment Gitleaks résout ce problème »Gitleaks utilise une approche basée sur des règles regex et des mots-clés pour détecter les secrets. Contrairement à d'autres outils, il ne vérifie pas si les secrets sont actifs, il se concentre sur la vitesse et la configurabilité.
Fonctionnement en trois étapes
Section intitulée « Fonctionnement en trois étapes »L'étape de classification est celle qui détermine la qualité des résultats, et elle repose sur deux mécanismes empilés. Gitleaks commence par chercher des mots-clés peu coûteux à repérer (AKIA, sk_live_, ghp_), puis n'applique l'expression régulière complète qu'aux lignes qui ont passé ce premier filtre. C'est ce pré-filtrage qui explique la vitesse de l'outil, et c'est aussi pourquoi une règle personnalisée sans champ keywords ralentit sensiblement un gros dépôt.
- Découverte : Gitleaks parcourt les sources (Git, fichiers, archives, stdin)
- Classification : chaque ligne est comparée aux 150+ règles intégrées
- Rapport : les secrets trouvés sont affichés avec leur emplacement exact
Points forts de Gitleaks
Section intitulée « Points forts de Gitleaks »Deux lignes de ce tableau sont des différenciateurs réels face aux autres scanners, les autres relèvent du confort. Le décodage automatique attrape les secrets encodés en base64 que la plupart des outils laissent passer, et le scan d'archives couvre le cas des artefacts de build livrés en .tar.gz où traînent des fichiers de configuration. En revanche, la configurabilité TOML a un revers : sans convention d'équipe, chaque dépôt finit avec son propre .gitleaks.toml et des allowlists qui divergent.
| Caractéristique | Détail |
|---|---|
| Rapidité | Écrit en Go, très performant |
| Configurabilité | Règles TOML personnalisables |
| Décodage | Base64, hex, URL encoding (v8.26+) |
| Archives | ZIP, tar.gz, 7z... (v8.27+) |
| Règles composites | Secrets multi-parties (v8.28+) |
| Intégration | Pre-commit, GitHub Actions, GitLab CI |
Ce que Gitleaks détecte
Section intitulée « Ce que Gitleaks détecte »La couverture est large sur les formats de jeton reconnaissables, c'est-à-dire ceux qui portent un préfixe fixe et une longueur constante. Elle est nettement plus faible sur les secrets sans forme identifiable : un mot de passe de base de données ou une clé interne maison ne seront détectés que par la règle générique generic-api-key, qui s'appuie sur l'entropie et génère beaucoup de faux positifs. C'est précisément pour ce cas qu'il faut écrire vos propres règles.
Gitleaks intègre plus de 150 règles pour détecter :
- Cloud providers : AWS, GCP, Azure, DigitalOcean
- Paiements : Stripe, PayPal, Square
- Authentification : GitHub, GitLab, Slack, Discord
- Bases de données : PostgreSQL, MySQL, MongoDB dans les URLs
- Clés privées : RSA, DSA, ECDSA, OpenSSH
- IA/ML : OpenAI, Anthropic, HuggingFace, Perplexity
Installation
Section intitulée « Installation »Gitleaks est un binaire Go statique sans dépendance, ce qui rend les quatre méthodes ci-dessous équivalentes en résultat. Le critère de choix est la traçabilité : sur un poste de développement, un gestionnaire de versions comme asdf ou mise permet d'aligner toute l'équipe sur la même version. En CI, l'image de conteneur épinglée par digest est préférable, sinon un changement de version amont peut faire échouer un pipeline du jour au lendemain sur des règles nouvellement ajoutées.
Téléchargez le binaire depuis les releases GitHub. Le projet publie un fichier de sommes à côté de chaque archive : récupérez les deux et contrôlez l'empreinte avant d'extraire quoi que ce soit.
VERSION="8.30.1"BASE="https://github.com/gitleaks/gitleaks/releases/download/v${VERSION}"
# Archive + fichier de sommes publié par le projetcurl -fsSLO "${BASE}/gitleaks_${VERSION}_linux_x64.tar.gz"curl -fsSLO "${BASE}/gitleaks_${VERSION}_checksums.txt"
# Contrôle de l'empreinte : doit afficher "... : OK"sha256sum --check --ignore-missing gitleaks_${VERSION}_checksums.txt
# Extraire et installer seulement si le contrôle est passétar xzf gitleaks_${VERSION}_linux_x64.tar.gz gitleakssudo install -m 0755 gitleaks /usr/local/bin/gitleaks
# Vérificationgitleaks version# 8.30.1Avec Homebrew :
brew install gitleaks
# Vérificationgitleaks versionL'image Docker est idéale pour les environnements CI/CD :
N'utilisez pas le tag latest : il change sans préavis et rend vos pipelines non reproductibles. Épinglez la version, et le digest dès que le scan conditionne un blocage de build.
# GitHub Container Registry, épinglé par digestIMG="ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f"docker pull "$IMG"
# Scanner un répertoire local en lecture seuledocker run --rm -v "$PWD:/path:ro" "$IMG" dir /path
# Le même contenu est publié sur Docker Hub sous zricethezav/gitleaksPour une gestion de versions flexible, avec la version inscrite dans un fichier versionné du dépôt. La syntaxe asdf set ci-dessous correspond à asdf 0.16 et suivantes ; sur les versions antérieures, la commande équivalente est asdf global gitleaks <version>.
# Ajouter le pluginasdf plugin add gitleaks
# Installer une version spécifiqueasdf install gitleaks 8.30.1
# Définir comme version globaleasdf set --home gitleaks 8.30.1Commandes principales
Section intitulée « Commandes principales »Depuis la version 8.19.0, Gitleaks utilise trois commandes principales : git, dir et stdin. Les anciennes commandes detect et protect sont dépréciées mais toujours fonctionnelles.
Scanner un dépôt Git
Section intitulée « Scanner un dépôt Git »La commande git scanne l'historique complet d'un dépôt Git, y compris toutes les branches.
# Scanner le dépôt dans le répertoire courantgitleaks git
# Scanner un dépôt spécifiquegitleaks git /chemin/vers/mon-repo
# Afficher les détails (mode verbose)gitleaks git -v
# Masquer la bannièregitleaks git --no-bannerExemple de sortie :
Finding: aws_access_key_id = AKIAIOSFODNN7EXAMPLESecret: AKIAIOSFODNN7EXAMPLERuleID: aws-access-tokenEntropy: 3.646439File: config.envLine: 4Commit: fbc14303ffbf8fb1c2c1914e8dda7d0121633acaAuthor: dev@example.comDate: 2024-06-16T17:17:40ZFingerprint: fbc14303ffbf8fb1c2c1914e8dda7d0121633aca:config.env:aws-access-token:4Link: https://github.com/org/repo/blob/fbc14303.../config.env#L4Cette sortie vous indique :
- Le type de secret :
aws-access-token - L'emplacement : fichier
config.env, ligne 4 - Le commit : hash, auteur, date
- Le lien direct : vers la ligne sur GitHub/GitLab
Filtrer par plage de commits
Section intitulée « Filtrer par plage de commits »--log-opts transmet sa valeur telle quelle à git log, sans validation par Gitleaks. Une option mal orthographiée fait donc échouer git, pas le scanner, et le message d'erreur remonté est celui de Git. C'est le levier principal pour rendre un scan supportable sur un dépôt ancien : limiter la plage divise le temps de scan d'autant, au prix d'un angle mort sur l'historique non couvert. Réservez cette réduction à la CI de pull request, et gardez un scan complet planifié à côté.
# Scanner uniquement les 10 derniers commitsgitleaks git --log-opts="--max-count=10"
# Scanner une plage de commitsgitleaks git --log-opts="HEAD~20..HEAD"
# Scanner uniquement une branche spécifiquegitleaks git --log-opts="--all develop..main"Scanner avant un commit (pre-commit)
Section intitulée « Scanner avant un commit (pre-commit) »Ces deux options ne couvrent pas le même périmètre. --staged analyse ce qui se trouve dans l'index Git, c'est-à-dire exactement ce que le commit va enregistrer. --pre-commit s'appuie sur un git diff et sert au hook officiel du projet, qui combine d'ailleurs les deux. Point de vigilance : un secret déjà présent dans un commit antérieur ne sera vu par aucune des deux, seul gitleaks git sur l'historique complet le trouvera.
# Scanner les fichiers stagésgitleaks git --staged
# Scanner avec git diff (mode pre-commit)gitleaks git --pre-commitScanner des fichiers ou répertoires
Section intitulée « Scanner des fichiers ou répertoires »dir ignore complètement Git : pas d'historique, pas de commit, pas d'auteur dans le rapport, seulement le chemin et la ligne. C'est la commande à utiliser sur un artefact de build, un dossier de configuration exporté ou un répertoire extrait d'une image de conteneur. Deux comportements à connaître : le répertoire .git/ est exclu du parcours, mais les fichiers cachés et les fichiers listés dans .gitignore sont bien scannés, ce qui remonte souvent un .env local que gitleaks git ne verrait jamais. Les alias file et directory désignent la même commande.
# Scanner un répertoiregitleaks dir /chemin/vers/dossier
# Scanner un fichier spécifiquegitleaks dir config.env
# Scanner plusieurs cheminsgitleaks dir fichier1.log fichier2.env /etc/config/Scanner l'entrée standard (stdin)
Section intitulée « Scanner l'entrée standard (stdin) »stdin ouvre le scan à tout ce qui produit du texte, et c'est là que se trouvent les fuites que personne ne cherche : journaux applicatifs, sorties de kubectl describe, exports de variables d'environnement. Le rapport ne peut évidemment pas indiquer de fichier ni de commit, seulement le numéro de ligne dans le flux. Prudence en revanche sur la commande qui alimente le tube, kubectl logs sur un pod bavard peut envoyer plusieurs gigaoctets.
# Scanner un fichier via pipecat config.env | gitleaks stdin
# Scanner la sortie d'une commandekubectl logs deployment/mon-app | gitleaks stdin
# Scanner un fichier décompressé à la voléegunzip -c logs.gz | gitleaks stdinFonctionnalités avancées
Section intitulée « Fonctionnalités avancées »Les quatre fonctions qui suivent servent des besoins différents mais partagent une logique : elles élargissent ou restreignent le périmètre du scan. Le décodage et le scan d'archives font apparaître des secrets invisibles à un scan naïf, la baseline et les formats de sortie servent à rendre les résultats exploitables au quotidien sans noyer les équipes sous les alertes déjà connues.
Décodage automatique (v8.26+)
Section intitulée « Décodage automatique (v8.26+) »Gitleaks peut décoder automatiquement les secrets encodés en base64, hexadécimal ou URL encoding. Par défaut, le décodage est activé avec une profondeur de 5.
# Activer le décodage récursif (profondeur 2)gitleaks dir /chemin --max-decode-depth=2
# Désactiver le décodagegitleaks dir /chemin --max-decode-depth=0Exemple : un token Stripe encodé en base64 sera détecté :
# Fichier contenant : c2tfbGl2ZV80ZUMzOUhxTHlqV0Rhcmp0VDF6ZHA3ZGMK
Finding: sk_live_4eC39HqLyjWDarjtT1zdp7dcSecret: sk_live_4eC39HqLyjWDarjtT1zdp7dcRuleID: stripe-access-tokenTags: [decoded:base64 decode-depth:1]Les tags decoded:base64 et decode-depth:1 indiquent que le secret a été trouvé après décodage.
Scan d'archives (v8.27+)
Section intitulée « Scan d'archives (v8.27+) »Le scan d'archives est désactivé par défaut (--max-archive-depth vaut 0), ce qui surprend beaucoup d'utilisateurs qui croient leurs .tar.gz couverts. Il faut l'activer explicitement. Montez la profondeur avec parcimonie : chaque niveau supplémentaire signifie une extraction sur disque, et une archive piégée contenant des milliers de fichiers imbriqués transforme le scan en saturation de l'espace temporaire du runner.
# Scanner une archive avec profondeur 1gitleaks dir archive.tar.gz --max-archive-depth=1
# Scanner des archives imbriquées (profondeur 3)gitleaks dir archives/ --max-archive-depth=3Formats supportés : zip, tar, tar.gz, tar.bz2, tar.xz, 7z, rar, et plus.
Le chemin dans les résultats indique l'emplacement dans l'archive :
File: nested.tar.gz!inner/files.tar!config/.envCela signifie : .env est dans files.tar, qui est dans nested.tar.gz.
Baseline : ignorer les secrets connus
Section intitulée « Baseline : ignorer les secrets connus »La baseline permet d'ignorer les secrets déjà identifiés lors de scans ultérieurs. Utile pour les projets avec un historique contenant des secrets déjà traités.
-
Créer la baseline en générant un rapport initial
Fenêtre de terminal gitleaks git --report-path baseline.json -
Utiliser la baseline pour les scans suivants
Fenêtre de terminal gitleaks git --baseline-path baseline.json --report-path findings.jsonSeuls les nouveaux secrets seront rapportés.
Formats de sortie
Section intitulée « Formats de sortie »Le choix du format dépend de qui lit le rapport. SARIF est le seul qui s'intègre nativement aux tableaux de bord de sécurité GitHub et GitLab, JUnit fait apparaître les fuites comme des tests en échec dans l'interface de la plupart des CI, et JSON est le format à conserver puisque c'est lui qui contient les fingerprint réutilisables dans un .gitleaksignore. Le format template reste réservé aux rapports internes qui doivent respecter un gabarit maison.
# JSON (défaut si --report-path est utilisé)gitleaks git -f json -r report.json
# CSVgitleaks git -f csv -r report.csv
# SARIF (pour GitHub Code Scanning)gitleaks git -f sarif -r report.sarif
# JUnit (pour CI/CD)gitleaks git -f junit -r report.xml
# Template personnaliségitleaks git -f template --report-template custom.tmpl -r report.txt
# Sortie JSON vers stdoutgitleaks git -f json -r -Configuration
Section intitulée « Configuration »Gitleaks se configure par un fichier .gitleaks.toml versionné avec le code. Deux erreurs coûtent cher ici. La première consiste à écrire une configuration sans useDefault = true, ce qui désactive silencieusement les 150 règles intégrées. La seconde consiste à empiler des exclusions jusqu'à ce que le scan ne renvoie plus rien, ce qui donne un pipeline vert et aucune sécurité. Traitez ce fichier comme du code de production : revue obligatoire, et une justification écrite pour chaque exclusion.
Ordre de précédence
Section intitulée « Ordre de précédence »Cet ordre explique la panne la plus fréquente en CI : un .gitleaks.toml correctement écrit mais ignoré, parce qu'une variable GITLEAKS_CONFIG traîne dans l'environnement du runner et prend le dessus. Notez aussi le point 4, le fichier est cherché dans le répertoire scanné, pas dans le répertoire courant. Scanner /opt/app depuis votre $HOME ne charge donc pas le .gitleaks.toml de votre $HOME. En cas de doute, --log-level=debug indique la configuration réellement retenue.
- Option
--configou-c - Variable d'environnement
GITLEAKS_CONFIG(chemin fichier) - Variable d'environnement
GITLEAKS_CONFIG_TOML(contenu TOML) - Fichier
.gitleaks.tomldans le répertoire scanné
Si aucune configuration n'est trouvée, Gitleaks utilise les règles par défaut.
Étendre la configuration par défaut
Section intitulée « Étendre la configuration par défaut »Le réflexe à prendre est useDefault = true. Sans cette ligne, votre fichier remplace entièrement le jeu de règles intégré au lieu de le compléter, et vous vous retrouvez avec un scanner qui ne cherche plus que vos propres motifs. disabledRules sert ensuite à retirer chirurgicalement une règle trop bruyante, generic-api-key étant de loin la première candidate. Désactivez-la seulement après avoir écrit vos règles maison, sinon vous perdez la seule détection qui couvre les secrets sans format connu.
# Titre de la configurationtitle = "Configuration personnalisée"
# Étendre la configuration par défaut[extend]useDefault = true
# Désactiver certaines règles par défautdisabledRules = ["generic-api-key"]Créer une règle personnalisée
Section intitulée « Créer une règle personnalisée »Deux champs conditionnent le résultat. keywords n'est pas décoratif : c'est le pré-filtre qui évite d'appliquer la regex à chaque ligne du dépôt, et l'oublier peut multiplier le temps de scan. entropy fixe un seuil de désordre en dessous duquel la correspondance est rejetée, ce qui écarte les valeurs de test du type int_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa. Enfin, la regex suit la syntaxe RE2 de Go, qui ne connaît ni les groupes arrière ni le lookahead : une expression copiée depuis PCRE peut être refusée au chargement.
[[rules]]# Identifiant uniqueid = "internal-api-key"
# Descriptiondescription = "Clé API interne de l'entreprise"
# Expression régulière (syntaxe Go)regex = '''int_[a-zA-Z0-9]{32}'''
# Mots-clés pour pré-filtrage (optimisation)keywords = ["int_", "internal_api"]
# Entropie minimum (optionnel)entropy = 3.5
# Tags pour le reportingtags = ["internal", "api-key"]Allowlists : exclure des faux positifs
Section intitulée « Allowlists : exclure des faux positifs »Une allowlist est un risque assumé, pas un correctif : tout ce qu'elle couvre cesse d'être vérifié, y compris les vrais secrets qui atterriraient plus tard au même endroit. Préférez donc les critères les plus étroits possibles. Exclure tests/ en bloc est commode mais large ; cibler un fichier de fixtures précis ou un motif de valeur connue, via regexes et stopwords, laisse le reste du répertoire sous surveillance. Documentez chaque entrée avec description, c'est ce champ qu'on relit six mois plus tard en se demandant pourquoi une règle est muette.
# Allowlist globale (s'applique à toutes les règles)[[allowlists]]description = "Fichiers de test et documentation"paths = [ '''tests/''', '''fixtures/''', '''\.md$''',]
# Allowlist pour une règle spécifique[[rules]]id = "aws-access-token"
[[rules.allowlists]] description = "Clés de test AWS" regexes = ['''AKIAIOSFODNN7EXAMPLE'''] stopwords = ["example", "test", "demo"]Allowlists partagées (v8.25+)
Section intitulée « Allowlists partagées (v8.25+) »targetRules résout un problème concret : avant la v8.25, exclure un même répertoire de test pour dix règles imposait de dupliquer dix blocs d'allowlist, avec la dérive qui s'ensuit quand on en oublie un. La portée reste explicite, seules les règles nommées sont concernées, ce qui évite l'effet de bord d'une allowlist globale qui aveugle aussi les règles ajoutées plus tard.
[[allowlists]]# Appliquer à des règles spécifiquestargetRules = ["aws-access-token", "generic-api-key"]description = "Fichiers de test"paths = ['''tests/.*\.json$''']Règles composites (v8.28+)
Section intitulée « Règles composites (v8.28+) »Les règles composites répondent au cas où une seule moitié du secret n'a aucune valeur. Un identifiant AWS AKIA... seul ne permet rien ; associé à sa clé secrète située quelques lignes plus bas, il donne un accès complet. Le paramètre withinLines définit la fenêtre de proximité acceptée. Un effet secondaire bienvenu : en exigeant les deux parties, ce type de règle réduit fortement les faux positifs sur les identifiants publics cités dans la documentation.
[[rules]]id = "aws-keypair"description = "Paire clé/secret AWS"regex = '''AKIA[0-9A-Z]{16}'''
# Règle requise : le secret doit être proche [[rules.required]] id = "aws-secret-pattern" withinLines = 5 # Le secret doit être dans les 5 lignes suivantesIgnorer un secret spécifique dans le code
Section intitulée « Ignorer un secret spécifique dans le code »Cette annotation vit dans le code, ce qui la rend visible en revue de code, contrairement à une allowlist enfouie dans un fichier de configuration. C'est son principal intérêt. Son principal danger aussi : n'importe qui peut la coller sur une vraie fuite pour faire passer un pipeline. Sur un dépôt sensible, l'option --ignore-gitleaks-allow permet de lancer un scan d'audit qui neutralise toutes ces annotations et révèle ce qu'elles masquent.
# Cette clé est un exemple pour la documentationAWS_KEY = "AKIAIOSFODNN7EXAMPLE" # gitleaks:allowFichier .gitleaksignore
Section intitulée « Fichier .gitleaksignore »Le fingerprint combine le commit, le fichier, l'identifiant de règle et le numéro de ligne. Cette précision est une qualité, chaque exception est chirurgicale, mais aussi une fragilité : réécrire l'historique ou déplacer la ligne change l'empreinte, et l'exception cesse silencieusement de s'appliquer. Récupérez toujours ces valeurs depuis un rapport JSON plutôt que de les composer à la main, et rappelez-vous qu'une entrée ici ne dispense jamais de révoquer le secret concerné.
# Format : fingerprint (depuis le rapport JSON)fbc14303ffbf8fb1c2c1914e8dda7d0121633aca:config.env:aws-access-token:477b2a3e56973785a52ba4ae4b8dac61d4bac016f:keys:private-key:6Intégration CI/CD
Section intitulée « Intégration CI/CD »Les trois intégrations ci-dessous ne se remplacent pas, elles se complètent. Le hook pre-commit est rapide et local mais contournable d'un --no-verify, la CI est incontournable mais n'agit qu'après le push. Une chaîne saine combine les deux : le hook pour le confort du développeur, la CI pour la garantie.
Pre-commit hook
Section intitulée « Pre-commit hook »Bloquez les secrets avant qu'ils ne soient commités. Le dépôt Gitleaks publie trois identifiants de hook : gitleaks compile le binaire en Go, gitleaks-docker passe par l'image de conteneur, gitleaks-system réutilise le binaire déjà installé sur le poste. Le premier est le plus simple, le troisième le plus rapide si votre équipe gère déjà la version via asdf ou mise.
repos: - repo: https://github.com/gitleaks/gitleaks rev: v8.30.1 hooks: - id: gitleaks-
Installer pre-commit
Fenêtre de terminal pip install pre-commit -
Créer le fichier de configuration
Fenêtre de terminal cat > .pre-commit-config.yaml << 'EOF'repos:- repo: https://github.com/gitleaks/gitleaksrev: v8.30.1hooks:- id: gitleaksEOF -
Installer les hooks
Fenêtre de terminal pre-commit install -
Tester
Fenêtre de terminal git add . && git commit -m "test"# Si un secret est détecté, le commit sera bloqué
Pour désactiver temporairement le hook :
SKIP=gitleaks git commit -m "skip check"GitHub Actions
Section intitulée « GitHub Actions »Utilisez l'action officielle Gitleaks. Trois points de ce workflow méritent votre attention. Le fetch-depth: 0 est obligatoire : sans lui, le checkout ne récupère qu'un commit et le scan d'historique ne voit rien. Les actions sont épinglées par SHA plutôt que par tag, car un tag Git peut être redéplacé vers un autre commit par le mainteneur ou un attaquant qui aurait pris la main sur le dépôt. Enfin, permissions: {} au niveau du workflow retire tous les droits par défaut, et chaque job ne récupère que ce dont il a besoin : contents: read pour cloner, pull-requests: write parce que l'action commente les pull requests.
name: Gitleaks
on: push: branches: [main] pull_request:
permissions: {}
jobs: gitleaks: runs-on: ubuntu-latest permissions: contents: read pull-requests: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: fetch-depth: 0 # Important : récupérer tout l'historique persist-credentials: false
- uses: gitleaks/gitleaks-action@e0c47f4f8be36e29cdc102c57e68cb5cbf0e8d1e # v3.0.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Uniquement pour les dépôts appartenant à une organisation GITLEAKS_LICENSE: ${{ secrets.GITLEAKS_LICENSE }}persist-credentials: false empêche actions/checkout de laisser le jeton d'authentification dans le fichier .git/config du runner, où n'importe quelle étape ultérieure du job pourrait le relire.
GitLab CI
Section intitulée « GitLab CI »Intégrez Gitleaks dans vos merge requests. Deux détails conditionnent le bon fonctionnement du job. D'abord, le chemin à scanner est un argument positionnel de la commande git, pas une option : l'ancien indicateur --source a disparu et renvoie désormais unknown flag. Ensuite, GIT_DEPTH: 0 est indispensable, car GitLab clone par défaut en profondeur limitée et un scan d'historique sur un clone tronqué ne prouve rien.
stages: - security
gitleaks: stage: security image: ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f variables: GIT_DEPTH: 0 # historique complet, sinon le scan est aveugle script: - gitleaks git "$CI_PROJECT_DIR" --verbose rules: - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - if: '$CI_COMMIT_BRANCH == "main"' allow_failure: falseLe code de sortie vaut 1 par défaut lorsqu'une fuite est trouvée, donc --exit-code n'est utile que pour changer cette valeur. Combiné à allow_failure: false, le pipeline s'arrête bien sur détection.
Pour générer un rapport SARIF compatible avec GitLab Security Dashboard, ajoutez le format de rapport et déclarez l'artefact. Conservez la clé paths en plus de reports : sans elle, le fichier n'est pas téléchargeable depuis l'interface, ce qui complique l'analyse quand le tableau de bord n'est pas disponible sur votre édition de GitLab.
gitleaks: stage: security image: ghcr.io/gitleaks/gitleaks:v8.30.1@sha256:c00b6bd0aeb3071cbcb79009cb16a60dd9e0a7c60e2be9ab65d25e6bc8abbb7f variables: GIT_DEPTH: 0 script: - gitleaks git "$CI_PROJECT_DIR" -f sarif -r gl-sast-report.sarif artifacts: reports: sast: gl-sast-report.sarif paths: - gl-sast-report.sarifDépannage
Section intitulée « Dépannage »Un point avant de lire ce tableau : « aucun résultat » n'est pas une bonne nouvelle en soi. Avant de conclure qu'un dépôt est propre, vérifiez que le scan a bien vu quelque chose, la ligne scanned ~N bytes de la sortie doit afficher un volume cohérent avec la taille du dépôt. Un 0 bytes signale presque toujours un clone tronqué en CI ou un chemin de départ erroné, pas l'absence de secrets.
| Symptôme | Cause probable | Solution |
|---|---|---|
| Aucun résultat | Pas de secret trouvé | Normal si le repo est propre |
| Faux positifs nombreux | Secrets de test, exemples | Utiliser .gitleaksignore ou allowlists |
| Scan très lent | Historique Git volumineux | Utiliser --log-opts="--max-count=100" |
| Erreur "no such file" | URL distante non supportée | Cloner le repo localement d'abord |
| Secret encodé non détecté | Décodage désactivé | Vérifier --max-decode-depth |
| Archive non scannée | Scan d'archives désactivé | Activer --max-archive-depth=1 |
Logs de débogage
Section intitulée « Logs de débogage »Le niveau debug répond à la question la plus utile en cas de comportement inattendu : quelle configuration a été chargée et quelles règles sont actives. Le niveau trace descend jusqu'au détail de chaque correspondance testée et sature vite un terminal ; réservez-le à l'analyse d'une règle personnalisée qui ne déclenche pas, en redirigeant la sortie vers un fichier.
# Niveau debuggitleaks git --log-level=debug
# Niveau trace (très verbeux)gitleaks git --log-level=traceFichier lent à scanner
Section intitulée « Fichier lent à scanner »Un scan qui traîne est presque toujours dû à quelques fichiers précis, pas à une lenteur générale : archives volumineuses, fichiers minifiés d'une seule ligne, jeux de données commités par erreur. Depuis la v8.26, Gitleaks les signale dans les journaux de débogage, ce qui permet de traiter la cause plutôt que d'abaisser la couverture du scan.
gitleaks git --log-level=debug 2>&1 | grep "slow"Ajoutez ces fichiers à une allowlist ou utilisez --max-target-megabytes :
# Ignorer les fichiers > 10 MBgitleaks git --max-target-megabytes=10Bonnes pratiques
Section intitulée « Bonnes pratiques »Détecter un secret coûte toujours plus cher que l'empêcher d'exister. Les trois volets ci-dessous suivent donc cet ordre de valeur : prévention d'abord, détection ensuite, remédiation en dernier recours parce qu'à ce stade le secret est déjà compromis.
Prévention : empêcher les secrets d'arriver dans Git
Section intitulée « Prévention : empêcher les secrets d'arriver dans Git »Ces quatre mesures se renforcent mutuellement, mais une seule change vraiment la donne : le gestionnaire de secrets. Tant qu'un secret existe sous forme de chaîne dans un fichier du poste de développement, il finira par être commité par accident. Les trois autres mesures réduisent la probabilité, la quatrième supprime la cause.
- Pre-commit hooks : bloquer les commits contenant des secrets
- Fichiers
.gitignore: exclure.env,*.pem,credentials.json - Gestionnaire de secrets : utiliser OpenBao, Vault, AWS Secrets Manager ou Passbolt
- Variables d'environnement : injecter les secrets au runtime
Détection : scanner régulièrement
Section intitulée « Détection : scanner régulièrement »Le scan de pull request et le scan périodique ne cherchent pas la même chose. Le premier porte sur un différentiel et doit rester rapide pour ne pas ralentir les équipes. Le second repasse sur l'historique complet et rattrape ce que les règles d'hier ne savaient pas détecter : chaque montée de version de Gitleaks ajoute des règles, donc un dépôt déclaré propre l'an dernier ne l'est pas forcément aujourd'hui.
- CI/CD : scanner chaque pull request et chaque push
- Scans périodiques : auditer l'organisation complète chaque semaine
- Nouveaux dépôts : ajouter Gitleaks dès la création
Remédiation : réagir aux découvertes
Section intitulée « Remédiation : réagir aux découvertes »L'ordre de cette liste est un ordre de priorité, pas une suite d'options. La rotation passe avant tout le reste, y compris avant le nettoyage de l'historique : tant que le secret reste valide, réécrire les commits ne protège de rien puisque des clones ont pu être faits entre-temps. Pour l'étape 3, git filter-branch est déprécié par le projet Git lui-même au profit de git-filter-repo, plus rapide et moins piégeux ; BFG Repo-Cleaner reste une alternative valable.
- Rotation immédiate : révoquer et recréer le secret exposé
- Audit des accès : vérifier les journaux d'utilisation du secret compromis
- Nettoyage de l'historique : utiliser
git filter-repoou BFG Repo-Cleaner - Post-mortem : comprendre comment le secret a été exposé
Comparaison avec TruffleHog
Section intitulée « Comparaison avec TruffleHog »Gitleaks et TruffleHog sont les deux outils open source les plus populaires pour la détection de secrets :
| Critère | Gitleaks | TruffleHog |
|---|---|---|
| Vitesse | ✅ Très rapide | ⚠️ Plus lent (vérification) |
| Vérification automatique | ❌ Non | ✅ Oui (800+ APIs) |
| Sources supportées | 3 (Git, dir, stdin) | 18 (Git, Docker, S3, Jenkins...) |
| Nombre de règles | 150+ | 800+ |
| Configuration | TOML flexible | YAML simple |
| Décodage | ✅ Base64, hex, URL | ✅ Base64, UTF-16 |
| Archives | ✅ ZIP, tar... | ✅ via --archive-max-depth |
| Règles composites | ✅ (v8.28+) | ❌ Non |
Recommandation :
- Gitleaks : idéal pour les hooks pre-commit et les scans CI/CD rapides
- TruffleHog : préférable pour les audits de sécurité avec vérification des secrets actifs
Une précision sur les deux dernières lignes du tableau, car les deux projets évoluent vite : TruffleHog dispose lui aussi de décodeurs (base64, UTF-16, échappements) et sait descendre dans les archives via ses options --archive-max-depth et --archive-max-size. Le vrai différenciateur reste ailleurs : Gitleaks privilégie la vitesse et le contrôle fin des règles, TruffleHog la vérification active des identifiants trouvés auprès des API concernées.
Vous pouvez utiliser les deux : Gitleaks en pre-commit pour la rapidité, TruffleHog en scan périodique pour la vérification.
À retenir
Section intitulée « À retenir »- Trois commandes :
git(historique),dir(fichiers),stdin(pipeline) - 150+ règles intégrées : AWS, Stripe, GitHub, Slack, et bien plus
- Décodage automatique : base64, hex et URL encoding, actif par défaut à la profondeur 5
- Scan d'archives : désactivé par défaut, à activer avec
--max-archive-depth - Baseline : ignorer les secrets déjà traités
- Pre-commit : bloquer les secrets avant qu'ils n'atteignent Git
- Rotation immédiate : un secret exposé est un secret compromis
- En CI : action épinglée par SHA,
permissions: {}, historique complet, image épinglée par digest
Prochaines étapes
Section intitulée « Prochaines étapes »Ressources
Section intitulée « Ressources »- Site officiel : github.com/gitleaks/gitleaks
- Playground : gitleaks.io/playground
- Configuration par défaut : gitleaks.toml
- Action GitHub : gitleaks-action