TP : Détecter des secrets dans un dépôt Git avec Gitleaks, TruffleHog et detect-secrets
Prérequis
Environnement technique
- Docker installé et fonctionnel.
- Git installé.
- Accès à un terminal Bash ou Zsh.
- jq installé pour lire et filtrer les rapports JSON.
- Python 3 installé.
- pip disponible.
- Accès Internet pour télécharger les images Docker et les dépendances Python.
Installer jq
Sur Debian / Ubuntu :
sudo apt updatesudo apt install -y jqSur macOS avec Homebrew :
brew install jqInstaller detect-secrets
Créer un environnement Python dédié :
python3 -m venv .venvsource .venv/bin/activateInstaller detect-secrets :
pip install detect-secretsVérifier l’installation :
detect-secrets --versiondetect-secrets-hook --helpOutils utilisés
Les outils utilisés via Docker sont :
ghcr.io/gitleaks/gitleaks:v8.30.0trufflesecurity/trufflehog:3.95.2L’outil suivant est utilisé localement via Python :
detect-secretsPrécaution
Ce TP crée volontairement de faux secrets dans un dépôt Git local.
Les secrets utilisés sont factices et servent uniquement à déclencher les outils de détection.
Ne jamais utiliser de vrais tokens, clés cloud, mots de passe ou secrets applicatifs dans un support de formation.
Objectifs
À la fin de ce TP, l’apprenant doit être capable de :
- Identifier des secrets exposés dans un dépôt Git.
- Comprendre les risques associés aux tokens, clés API, clés cloud et mots de passe en clair.
- Scanner un répertoire de dépôt avec Gitleaks.
- Scanner un historique Git avec Gitleaks.
- Scanner un système de fichiers avec TruffleHog.
- Scanner un dépôt Git local avec TruffleHog.
- Générer une baseline avec detect-secrets.
- Utiliser detect-secrets-hook pour bloquer l’ajout d’un nouveau secret.
- Lire les rapports JSON produits par les outils.
- Comparer les résultats de plusieurs outils de détection.
- Comprendre l’intérêt d’un contrôle de secrets dans une chaîne DevSecOps.
Commandes
1. Créer l’arborescence du TP
mkdir -p tp-detection-secrets-gitcd tp-detection-secrets-git
mkdir -p reports2. Télécharger les images Docker des outils
docker pull ghcr.io/gitleaks/gitleaks:v8.30.0docker pull trufflesecurity/trufflehog:3.95.23. Vérifier les versions des outils Docker
docker run --rm ghcr.io/gitleaks/gitleaks:v8.30.0 versiondocker run --rm trufflesecurity/trufflehog:3.95.2 --version4. Créer un dépôt Git local de démonstration
mkdir repo-vulnerablecd repo-vulnerable
git initgit config user.email "formation@example.com"git config user.name "Formation Sécurité Cloud"5. Créer un fichier applicatif sans secret
cat > app.py <<'EOF'print("Application de démonstration")EOF6. Créer un fichier contenant de faux secrets
cat > config.env <<'EOF'AWS_ACCESS_KEY_ID=AKIA1234567890ABCDEFAWS_SECRET_ACCESS_KEY=abcdEFGH1234567890abcdEFGH1234567890ABCDDATABASE_PASSWORD=SuperSecretPassword123!SLACK_BOT_TOKEN=xoxb-TRAINTOKEN-TRAINTOKEN-TRAININGTRAININGTRAININGTRAININGTRAININGEOF7. Créer un faux fichier de clé privée
cat > private-key.pem <<'EOF'-----BEGIN RSA PRIVATE KEY-----MIIEpAIBAAKCAQEA0FakeTrainingKeyOnlyDoNotUseThisValueForAnythingFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFakeFake-----END RSA PRIVATE KEY-----EOF8. Ajouter les fichiers au dépôt Git
git add app.py config.env private-key.pemgit commit -m "Ajout initial avec secrets factices"9. Vérifier l’historique Git
git log --oneline10. Revenir à la racine du TP
cd ..11. Scanner le répertoire avec Gitleaks
Cette commande scanne les fichiers présents dans le répertoire du dépôt.
L’option --redact masque les valeurs des secrets dans le rapport. Les findings restent visibles, mais les valeurs sensibles sont remplacées par des valeurs masquées.
docker run --rm \ -v "$PWD/repo-vulnerable:/repo" \ -v "$PWD/reports:/reports" \ ghcr.io/gitleaks/gitleaks:v8.30.0 \ dir /repo \ --report-format json \ --report-path /reports/gitleaks-dir.json \ --redact \ --exit-code 1echo "Code de retour Gitleaks dir : $?"12. Vérifier le rapport Gitleaks
ls -lh reports/gitleaks-dir.json13. Lire le nombre de findings Gitleaks
jq 'length' reports/gitleaks-dir.json14. Afficher une synthèse des findings Gitleaks
jq -r '.[]? | [.RuleID, .File, .StartLine, .Description] | @tsv' reports/gitleaks-dir.json15. Scanner le dépôt Git avec Gitleaks
Cette commande scanne l’historique Git du dépôt.
docker run --rm \ -v "$PWD/repo-vulnerable:/repo" \ -v "$PWD/reports:/reports" \ ghcr.io/gitleaks/gitleaks:v8.30.0 \ git /repo \ --report-format json \ --report-path /reports/gitleaks-git.json \ --redact \ --exit-code 1echo "Code de retour Gitleaks git : $?"16. Lire le nombre de findings Gitleaks dans l’historique Git
jq 'length' reports/gitleaks-git.json17. Scanner le système de fichiers avec TruffleHog
Cette commande scanne les fichiers présents dans le dépôt.
TruffleHog produit une sortie au format JSON Lines : chaque finding est écrit comme un objet JSON séparé.
docker run --rm \ -v "$PWD:/pwd" \ trufflesecurity/trufflehog:3.95.2 \ filesystem /pwd/repo-vulnerable \ --json \ --no-verification \ > reports/trufflehog-filesystem.jsonecho "Code de retour TruffleHog filesystem : $?"18. Lire le nombre de findings TruffleHog filesystem
jq -s 'length' reports/trufflehog-filesystem.json19. Afficher une synthèse des findings TruffleHog filesystem
jq -rs '.[] | [ .DetectorName, .SourceName, (.SourceMetadata.Data.Filesystem.file? // .SourceMetadata.Data.Filesystem.path? // "non renseigné"), (.Raw // .Redacted // "non renseigné")] | @tsv' reports/trufflehog-filesystem.json20. Scanner le dépôt Git local avec TruffleHog
Cette commande scanne l’historique Git du dépôt local.
docker run --rm \ -v "$PWD:/pwd" \ trufflesecurity/trufflehog:3.95.2 \ git file:///pwd/repo-vulnerable \ --json \ --no-verification \ > reports/trufflehog-git.jsonecho "Code de retour TruffleHog git : $?"21. Lire le nombre de findings TruffleHog git
jq -s 'length' reports/trufflehog-git.json22. Afficher une synthèse des findings TruffleHog git
jq -rs '.[] | [ .DetectorName, .SourceName, (.SourceMetadata.Data.Git.file? // "non renseigné"), (.SourceMetadata.Data.Git.line? // "non renseigné")] | @tsv' reports/trufflehog-git.json23. Générer une baseline detect-secrets
Vérifier que l’environnement Python virtuel est actif avant d’exécuter cette commande.
source .venv/bin/activatedetect-secrets scan repo-vulnerable --all-files > reports/detect-secrets-baseline.jsonecho "Code de retour detect-secrets scan : $?"24. Vérifier la baseline detect-secrets
ls -lh reports/detect-secrets-baseline.json25. Lire le nombre de fichiers contenant des secrets selon detect-secrets
jq '.results | keys | length' reports/detect-secrets-baseline.json26. Lire le nombre total de findings detect-secrets
jq '([.results[]? | length] | add) // 0' reports/detect-secrets-baseline.json27. Afficher une synthèse des findings detect-secrets
jq -r '.results | to_entries[]? as $file | $file.value[]? | [$file.key, .type, .line_number] | @tsv' reports/detect-secrets-baseline.json28. Créer un nouveau fichier contenant un faux secret
Cette étape simule l’ajout d’un nouveau secret après la création de la baseline.
Le fichier est ajouté à l’index Git avec git add, mais il n’est pas commité. Il est donc visible par les scans de répertoire, mais pas encore par les scans d’historique Git.
cd repo-vulnerable
cat > new-secret.env <<'EOF'GITHUB_TOKEN=ghp_1234567890abcdefghijklmnopqrstuv1234EOF
git add new-secret.env29. Contrôler les fichiers staged avec detect-secrets-hook
Cette commande simule un contrôle de type pré-commit.
Vérifier que l’environnement Python virtuel est toujours actif avant d’exécuter cette commande.
source ../.venv/bin/activate
if ! command -v detect-secrets-hook >/dev/null 2>&1; then echo "detect-secrets-hook non trouvé — vérifier que l'environnement Python virtuel est actif" exit 1figit diff --staged --name-only -z | xargs -0 detect-secrets-hook --baseline ../reports/detect-secrets-baseline.jsonecho "Code de retour detect-secrets-hook : $?"30. Revenir à la racine du TP
cd ..31. Générer une nouvelle baseline après ajout du secret
detect-secrets scan repo-vulnerable --all-files > reports/detect-secrets-baseline-updated.json32. Comparer le nombre de findings avant et après ajout
echo "Baseline initiale :"jq '([.results[]? | length] | add) // 0' reports/detect-secrets-baseline.json
echo "Baseline mise à jour :"jq '([.results[]? | length] | add) // 0' reports/detect-secrets-baseline-updated.json33. Scanner à nouveau avec Gitleaks après ajout du nouveau secret
Ce scan lit les fichiers présents dans le répertoire. Il peut donc détecter new-secret.env, même si le fichier n’a pas été commité.
docker run --rm \ -v "$PWD/repo-vulnerable:/repo" \ -v "$PWD/reports:/reports" \ ghcr.io/gitleaks/gitleaks:v8.30.0 \ dir /repo \ --report-format json \ --report-path /reports/gitleaks-dir-updated.json \ --redact \ --exit-code 1echo "Code de retour Gitleaks dir après ajout : $?"34. Lire le nombre de findings Gitleaks après ajout
jq 'length' reports/gitleaks-dir-updated.json35. Scanner à nouveau avec TruffleHog après ajout du nouveau secret
Ce scan lit les fichiers présents dans le répertoire. Il peut donc détecter new-secret.env, même si le fichier n’a pas été commité.
docker run --rm \ -v "$PWD:/pwd" \ trufflesecurity/trufflehog:3.95.2 \ filesystem /pwd/repo-vulnerable \ --json \ --no-verification \ > reports/trufflehog-filesystem-updated.jsonecho "Code de retour TruffleHog après ajout : $?"36. Lire le nombre de findings TruffleHog après ajout
jq -s 'length' reports/trufflehog-filesystem-updated.json37. Construire un rapport de synthèse local
{ echo "# Rapport TP Détection de secrets dans un dépôt Git" echo echo "## Outils utilisés" echo echo "| Outil | Usage | Rapport |" echo "|---|---|---|" echo "| Gitleaks | Scan du répertoire | reports/gitleaks-dir.json |" echo "| Gitleaks | Scan de l'historique Git | reports/gitleaks-git.json |" echo "| TruffleHog | Scan du système de fichiers | reports/trufflehog-filesystem.json |" echo "| TruffleHog | Scan de l'historique Git | reports/trufflehog-git.json |" echo "| detect-secrets | Baseline initiale | reports/detect-secrets-baseline.json |" echo "| detect-secrets | Baseline mise à jour | reports/detect-secrets-baseline-updated.json |" echo echo "## Synthèse Gitleaks dir" echo echo '```json' jq 'length' reports/gitleaks-dir.json echo '```' echo echo "## Synthèse Gitleaks git" echo echo '```json' jq 'length' reports/gitleaks-git.json echo '```' echo echo "## Synthèse TruffleHog filesystem" echo echo '```json' jq -s 'length' reports/trufflehog-filesystem.json echo '```' echo echo "## Synthèse TruffleHog git" echo echo '```json' jq -s 'length' reports/trufflehog-git.json echo '```' echo echo "## Synthèse detect-secrets" echo echo '```json' jq '([.results[]? | length] | add) // 0' reports/detect-secrets-baseline.json echo '```' echo echo "## Points à observer" echo echo "- Les secrets peuvent être présents dans les fichiers courants." echo "- Les secrets peuvent rester présents dans l'historique Git." echo "- Un secret doit être révoqué même s'il est supprimé du code." echo "- Une baseline permet de distinguer un stock existant de nouveaux secrets introduits." echo "- Un contrôle de secrets peut être intégré dans un hook Git ou une chaîne CI/CD."} > reports/secrets-detection-summary.md38. Afficher le rapport de synthèse
cat reports/secrets-detection-summary.md39. Lister les rapports générés
find reports -maxdepth 1 -type f -printNettoyage optionnel
40. Supprimer le dossier du TP
Se placer dans le dossier parent avant d’exécuter cette commande.
cd ..rm -rf tp-detection-secrets-gitRésultat attendu
| Fichier produit | Description |
|---|---|
reports/gitleaks-dir.json | Secrets détectés dans le répertoire par Gitleaks |
reports/gitleaks-git.json | Secrets détectés dans l’historique Git par Gitleaks |
reports/trufflehog-filesystem.json | Secrets détectés dans les fichiers par TruffleHog |
reports/trufflehog-git.json | Secrets détectés dans l’historique Git par TruffleHog |
reports/detect-secrets-baseline.json | Baseline initiale créée par detect-secrets |
reports/detect-secrets-baseline-updated.json | Baseline mise à jour après ajout d’un nouveau secret |
reports/gitleaks-dir-updated.json | Scan Gitleaks après ajout du nouveau secret |
reports/trufflehog-filesystem-updated.json | Scan TruffleHog après ajout du nouveau secret |
reports/secrets-detection-summary.md | Rapport de synthèse du TP |
| Observation | Résultat attendu |
|---|---|
| Clés cloud dans des fichiers de configuration | Détectées par Gitleaks et TruffleHog |
| Tokens dans le dépôt | Détectés par au moins un outil |
| Clé privée sensible | Détectée comme secret à haut risque |
| Historique Git | Des secrets supprimés du code restent détectables dans l’historique |
| Baseline detect-secrets | Permet de distinguer les secrets connus des nouveaux secrets |
| Hook Git ou pipeline bloquant | Un contrôle de secrets peut bloquer un commit ou une merge request |
Aucun vrai secret ne doit être utilisé pendant ce TP.