Aller au contenu principal
own2pwn
Fuite de secrets : quatre scanners mesurés, et ce qu'aucun ne voit

Fuite de secrets : quatre scanners mesurés, et ce qu'aucun ne voit

gitleaks, trufflehog, detect-secrets et la passe regex de SecAI sur deux corpus, même règle pour tous : le classement s'inverse, et réunis ils ratent la moitié des secrets de leaky-repo.

Maxime J17 min de lectureMis à jour le

Des secrets qui traînent sur votre périmètre ?

Notre module Leaks & Secrets les traque en continu, avant l'attaquant.

Détecter mes secrets exposés

Un développeur pressé colle une clé AWS dans un script pour débloquer un déploiement du vendredi soir. Ça marche, il oublie, il commit, il push. La CI passe au vert, tout le monde rentre chez soi. À l'autre bout d'Internet, un bot qui lit le flux public de GitHub récupère la clé, et quelques minutes plus tard elle démarre des instances de minage sur votre compte cloud. La facture arrivera en fin de mois.

Contre cette fuite de secrets, la réponse habituelle tient en une phrase : mettez un scanner de secrets dans la CI. Reste à savoir lequel, et surtout ce qu'il voit. On a donc posé quatre scanners sur deux corpus et compté, ligne par ligne, avec la même règle pour tous : gitleaks, trufflehog, detect-secrets, et la passe regex et entropie de SecAI, notre propre produit. Deux résultats tiennent la suite de l'article. Le classement s'inverse d'un corpus à l'autre. Et même réunis, les quatre ratent plus de la moitié des secrets du corpus le plus ancien.

périmètre
lignes à trouver dans leaky-repocontre 96 annoncées par le dépôt, écart expliqué plus bas
88
jetons fictifs à préfixerapportés à part, jamais additionnés
25
scanners, dont le nôtremême règle de comptage pour tous
4
accès réseauaucune vérification de validité en ligne
0
Banc own2pwn du 6 octobre 2026. leaky-repo au commit 2e95135 (2020), arbre de fichiers sans historique git, 88 lignes porteuses d'un secret ; lot fictif de 25 jetons écrit pour le banc.

Un secret n'est pas une vulnérabilité, c'est une clé

On range volontiers les fuites de secrets dans la même case que les injections ou les XSS. C'est une erreur de modèle mental. Une XSS demande un effort d'exploitation ; un secret exposé est déjà l'accès. Le coût pour l'attaquant tombe à zéro, et la fenêtre entre l'exposition et l'abus se compte en minutes.

Le volume ne baisse pas. GitGuardian a compté 12,8 millions de nouveaux secrets sur des dépôts GitHub publics en 2023, puis 23,8 millions en 2024, extraits de 1,4 milliard de commits. Le même éditeur rapporte que 70 % des secrets fuités en 2022 fonctionnaient encore deux ans plus tard : la plupart des identifiants qui fuitent ne sont jamais révoqués.

Cadre : cet article est défensif

On décrit les mécanismes d'exposition et d'exploitation pour vous aider à protéger votre organisation. Chercher, collecter ou utiliser des secrets qui ne vous appartiennent pas est illégal, même s'ils traînent sur un dépôt public. Les deux corpus du banc sont publics ou fictifs, et aucun secret n'est recopié dans cette page.

Comment les secrets fuitent vraiment

Le commit Git, et l'historique qui n'oublie rien

C'est la source numéro un. Un secret codé en dur, committé une fois, reste dans l'historique Git même si le commit suivant le supprime : la valeur vit dans le diff du commit fautif, et un git log -p la ressort. Un dépôt privé rendu public un jour (rachat, open-sourcing, erreur de visibilité) expose d'un coup tout son passé. Retenez ce point pour la suite : le banc ci-dessous a scanné un arbre de fichiers, pas un historique, et la plupart des scanners ne lisent l'historique que si on le leur demande.

bash
# Le secret a été "supprimé" au commit HEAD... mais il est toujours là :
git log -p -S 'AKIA' --all        # cherche toute clé AWS dans TOUT l'historique
git rev-list --all | xargs git grep 'api_key' 2>/dev/null

Hors du dépôt : bundle, .env, bucket, image, compte perso

Tout ce qui est injecté dans un bundle front (variables préfixées NEXT_PUBLIC_, VITE_, REACT_APP_) est livré au navigateur, lisible par n'importe quel visiteur. Un .env copié dans le webroot répond un 200 OK aux scanners d'opportunité qui testent cette URL sur tout le web, comme les .git/config exposés et les .env.bak oubliés. Un bucket mal configuré devient lisible par une URL devinable, et un SSRF vers la métadonnée cloud rend des identifiants d'instance, un classique des erreurs de configuration cloud visibles depuis l'extérieur. Une image Docker publique garde ses ARG de build dans ses couches, un echo $TOKEN de débogage finit dans les logs de CI. Et le cas le plus dur à voir : un développeur pousse un projet perso, avec un bout de configuration de son employeur, sur un compte que personne ne surveille. Cet angle mort relève de la gestion du shadow IT.

surfaces-de-fuite
Surface
Images Docker & logs CI
Couches de build, ARG gravés, variables loguées en clair.
Surface
.env / config exposés
Servis en clair par une mauvaise route ou un backup oublié.
Surface
Bundle JS front
Livré au navigateur. Le minify ne chiffre rien.
Surface
Historique Git
Commits, branches, forks, clones : la valeur survit à sa suppression.
Le secret
Une clé d'API / un token
Une chaîne qui authentifie un service ou un utilisateur.
Un même secret peut fuiter par plusieurs couches à la fois. Le code n'est que la plus visible.

Ce qu'un attaquant en fait, et à quelle vitesse

Un secret public n'attend pas qu'un humain tombe dessus. Des bots filtrent le flux de commits en temps réel et testent chaque identifiant dans la foulée, au point que GitHub demande de révoquer ou de faire tourner un secret committé avant toute autre action. Les honeytokens, des identifiants leurres semés pour mesurer le temps de réaction, le confirment : dans le rapport 2023 d'Orca Security, une clé AWS leurre exposée sur GitHub a été utilisée en deux minutes.

cycle-fuite
Développeur
Commit d'un secret
Une clé en dur part sur un dépôt public. La CI passe au vert.
Bots
Lecture du flux public
Filtrent les commits en temps réel, extraient la clé.
Attaquant
Validation & abus
Teste la clé, démarre du minage, exfiltre des données, pivote.
Victime
La facture, ou pire
Coûts cloud, fuite de données, mouvement latéral vers le SI.
De l'oubli du développeur à l'abus : le cycle se boucle en minutes, pas en jours.

Une clé cloud surprivilégiée sert au minage, directement monétisable, ou à l'exfiltration, et le sujet devient alors une fuite de données avec son horloge de 72 heures. Un token d'emailing ou de paiement sert à la fraude : le fraudeur qui écrit depuis votre propre outil n'a plus besoin d'usurper votre identité d'entreprise, il l'emprunte.

Deux incidents de 2022 montrent les deux visages du problème. Chez Toyota, un sous-traitant avait poussé en décembre 2017 du code de T-Connect sur un dépôt GitHub public, avec une clé d'accès au serveur de données clients. Le dépôt n'a été fermé que le 15 septembre 2022, et la clé ouvrait les adresses e-mail et numéros de gestion de 296 019 clients : aucune revue de code interne ne pouvait l'attraper, puisque le dépôt n'était pas celui de Toyota. Chez Uber, l'attaquant entré par ingénierie sociale a trouvé sur un partage réseau un script PowerShell contenant des identifiants admin en dur du coffre à privilèges, qui ouvrait à son tour AWS, Slack et le reste. Le premier cas dit qu'on ne protège que ce qu'on voit, le second qu'un secret commande toute une chaîne d'accès.

Le banc : quatre scanners de secrets, deux corpus, une règle

Le corpus principal est leaky-repo, un dépôt public fait pour ça, figé au commit 2e95135 de février 2020 : 49 fichiers scannés, pour l'essentiel des configurations réalistes (dotfiles, .netrc, wp-config.php, dump SQL, clés SSH, profils FileZilla) et un fichier CSV qui annonce 96 lignes à risque. Relues fichier par fichier, 88 ont été retenues : le CSV compte par exemple trois mots de passe dans un fichier où deux seulement sont marqués comme risque, ou des adresses e-mail comme des secrets. La vérité terrain vient du dépôt, jamais de la sortie d'un outil. Le second corpus est un lot de 25 jetons fictifs aux formats modernes (OpenAI, GitHub, Stripe, npm, Slack...), écrit pour le banc et rapporté à part.

Les quatre outils ont tourné en configuration par défaut, une seule fois chacun, sur le même arbre de fichiers, sans historique git, et sans réseau : trufflehog dans un conteneur en --network none, les trois autres sous unshare -rn, avec une sonde consignée avant chaque exécution pour prouver que la connexion était impossible. Personne n'a donc pu vérifier un jeton en ligne.

bash
# gitleaks 8.28.0, binaire officiel, config par défaut
gitleaks dir . --report-format json --report-path gitleaks.json --exit-code 0 --no-banner

# trufflehog 3.99.0, image épinglée par digest, sans réseau
docker run --rm --network none -v "$PWD:/pwd:ro,z" trufflesecurity/trufflehog \
  filesystem /pwd --no-verification --no-update --json

# detect-secrets 1.5.0, dépendances épinglées par empreinte
detect-secrets scan --all-files --no-verify

Le quatrième outil est le nôtre, et il faut dire exactement lequel. C'est la passe regex et entropie de SecAI, le worker déterministe qui cherche les secrets pendant un scan : ni modèle de langage, ni base, ni réseau. La règle SAST de SecAI sur les secrets codés en dur, qui passe par un vérificateur LLM, n'a pas été exécutée, pas plus que sa passe sur l'historique git. Aucun outil du banc n'a appelé de modèle de langage. Le harnais qui lance ce worker n'est pas public ; les trois autres outils se rejouent avec les commandes ci-dessus.

La règle de comptage est la même pour les quatre. Une alerte n'est un vrai positif que si la valeur qu'elle capture contient le secret, et toutes les alertes appariées ont été relues à la main. Signaler la bonne ligne avec le mauvais morceau ne suffit pas : detect-secrets, par exemple, ne retient des jetons GitHub et GitLab que leur préfixe : ces alertes comptent comme faux positifs, et le jeton GitLab est perdu. Une seule tolérance : une alerte sur l'en-tête d'une clé privée (la ligne BEGIN ... PRIVATE KEY) est créditée, parce qu'elle désigne le bloc qui est le secret.

Ce banc a été refait

Un premier passage a été jeté après contre-expertise, pour deux raisons. detect-secrets y avait tourné avec sa vérification en ligne, qui supprime les jetons jugés invalides auprès de leur émetteur : il ne jouait pas à armes égales. Et la règle de contenu n'était appliquée qu'à un cas au lieu de toutes les alertes. Tout ce qui suit vient du second passage, réseau coupé pour tous, règle appliquée partout. Ce second passage coûte aussi trois lignes à detect-secrets sur le lot fictif (20 → 17) : il n'y capture que l'identifiant AWS, le début d'une clé Stripe et le préfixe d'un jeton GitLab.

Le classement s'inverse selon le corpus

rappel
Rappel par ligne de chaque scanner de secrets, sur les deux corpus
  • leaky-repo (88 lignes, 2020)
  • lot fictif (25 jetons à préfixe)
Rappel par ligne de chaque scanner de secrets, sur les deux corpusdetect-secrets 1.5.040,9 %68,0 %Passe regex et entropie de SecAIaprès correctif31,8 %80,0 %gitleaks 8.28.023,9 %92,0 %trufflehog 3.99.09,1 %76,0 %Passe regex et entropie de SecAIpremier passage, avant correctif4,5 %64,0 %
Rappel par ligne de chaque scanner de secrets, sur les deux corpus
Catégorieleaky-repo (88 lignes, 2020) (%)lot fictif (25 jetons à préfixe) (%)
detect-secrets 1.5.040,968,0
Passe regex et entropie de SecAI31,880,0
gitleaks 8.28.023,992,0
trufflehog 3.99.09,176,0
Passe regex et entropie de SecAI4,564,0
Banc own2pwn du 6 octobre 2026. gitleaks 8.28.0, trufflehog 3.99.0, detect-secrets 1.5.0 et la passe regex et entropie de SecAI (worker SecretScanner, commits 6f9cb410 et de5bfb3), configurations par défaut, une exécution par outil, réseau coupé pour tous. leaky-repo au commit 2e95135 (2020), arbre de fichiers sans historique git, 88 lignes porteuses d'un secret ; lot fictif de 25 jetons écrit pour le banc. Rappel = vrais positifs divisés par le nombre de lignes porteuses d'un secret. Une alerte n'est un vrai positif que si la valeur capturée contient le secret ; une alerte sur l'en-tête d'une clé privée est créditée. Les deux corpus ne s'additionnent pas.

Sur leaky-repo, detect-secrets trouve 36 lignes sur 88 (40,9 %) et finit premier. Sur le lot de jetons modernes, il finit dernier, à 17 sur 25 (68 %). gitleaks fait l'inverse : 23,9 % sur leaky-repo, 92 % sur le lot fictif. L'explication se lit dans le contenu des corpus. leaky-repo est un vieux poste de travail : 27 mots de passe en clair, 11 mots de passe chiffrés ou encodés, 13 hachages, des clés secrètes de frameworks web. detect-secrets cherche des mots-clés (password, secret) et de l'entropie, et ramasse 13 des 27 mots de passe en clair. gitleaks et trufflehog cherchent des motifs nommés, un préfixe et une longueur par fournisseur : aucun des deux ne trouve un seul de ces 27 mots de passe, mais ils excellent sur les jetons à préfixe du lot fictif.

trufflehog est le plus pénalisé, à 9,1 % sur leaky-repo, et ce chiffre dit surtout quelque chose de sa conception : ses détecteurs visent des formats précis, souvent avec un élément compagnon (un domaine, un identifiant de compte). Il est aussi conçu pour vérifier les jetons en ligne ; le banc l'en a privé, ce qui ne réduit pas son rappel ici, la vérification ne pouvant que retirer des alertes. Sur le lot fictif, il remonte à 76 %. Côté précision, sur leaky-repo, gitleaks et la passe de SecAI sont à 100 %, detect-secrets et trufflehog entre 80 et 95 %, sur deux faux positifs chacun. Il ne faut pas en tirer de conclusion : les deux corpus sont saturés de secrets et ne contiennent presque pas de leurres.

leaky-repo
OutilVPFNFPRappel par ligneRappel sur valeurs uniquesPrécision
detect-secrets 1.5.03652240,9 %36/83 (43,4 %)94,7 %
Passe regex et entropie de SecAI, après correctif2860031,8 %25/83 (30,1 %)100 %
Même passe, sans les quatre retouches de règles2662029,5 %23/83 (27,7 %)100 %
gitleaks 8.28.02167023,9 %18/83 (21,7 %)100 %
trufflehog 3.99.088029,1 %8/83 (9,6 %)80 %
Passe regex et entropie de SecAI, premier passage48404,5 %4/83 (4,8 %)100 %
Banc own2pwn du 6 octobre 2026, corpus leaky-repo (88 lignes, 83 valeurs distinctes : cinq paires de lignes portent la même valeur dans le même fichier). VP = vrais positifs, FN = secrets ratés, FP = faux positifs. Une alerte n'est un vrai positif que si la valeur capturée contient le secret ; une alerte sur l'en-tête d'une clé privée est créditée. Précision = VP / (VP + FP). Source : results.json du banc, clé leaky_repo_88.
lot fictif
OutilVPFNFPRappel par ligneRappel sur valeurs uniquesPrécision
gitleaks 8.28.0232092 %23/25 (92 %)100 %
Passe regex et entropie de SecAI, après correctif205080 %20/25 (80 %)100 %
Même passe, sans les quatre retouches de règles196076 %19/25 (76 %)100 %
trufflehog 3.99.0196076 %19/25 (76 %)100 %
detect-secrets 1.5.0178468 %17/25 (68 %)81 %
Passe regex et entropie de SecAI, premier passage169064 %16/25 (64 %)100 %
Banc own2pwn du 6 octobre 2026, lot fictif de 25 jetons, tous distincts : le rappel par ligne et le rappel sur valeurs uniques coïncident. Une alerte n'est un vrai positif que si la valeur capturée contient le secret ; une alerte sur l'en-tête d'une clé privée est créditée. Source : results.json du banc, clé synth_fictifs_25.

Créditer le début de clé Stripe capturé par detect-secrets le ferait passer à 18/25 (72 %), toujours derrière trufflehog.

La tolérance sur les en-têtes de clé privée profite à deux outils. Sans elle, detect-secrets tombe à 37,5 % sur leaky-repo et 60 % sur le lot fictif, la passe de SecAI à 28,4 % et 72 %, ce qui la place derrière trufflehog sur le lot fictif ; gitleaks et trufflehog ne bougent pas.

La passe regex et entropie de SecAI : 4,5 %, deux défauts, un correctif, 31,8 %

Au premier passage, la passe regex et entropie de SecAI a trouvé 4 lignes sur 88 dans leaky-repo, soit 4,5 %. Le dernier du banc, et de loin. L'analyse a fait ressortir deux défauts. Le premier tenait à la sélection des fichiers : le worker ne lisait que les fichiers dont l'extension figurait dans une liste, si bien qu'il sautait les dotfiles et les fichiers sans extension, donc .bash_profile, id_rsa, .s3cfg et une bonne part de ce que contient un poste de développeur. Le second, sa règle générique ne reconnaissait pas les paires clé-valeur JSON. Le correctif remplace la liste d'extensions par une liste d'exclusion, réécrit la règle générique, et apporte au passage quatre retouches de règles sans rapport avec ces deux défauts, dont deux règles nouvelles : une pour les clés PuTTY, une pour les URL contenant des identifiants.

Après correctif, la même passe trouve 28 lignes sur 88, soit 31,8 %. Pour isoler ce qui vient des deux défauts corrigés, une variante retire ces quatre retouches : elle obtient 26 lignes, 29,5 %. Les retouches n'apportent donc que deux lignes, la clé PuTTY et une URL MongoDB ; le reste vient de la sélection de fichiers et de la règle générique. Et même corrigée, la passe de SecAI reste derrière detect-secrets sur leaky-repo (31,8 % contre 40,9 %). Elle ne trouve aucun des 27 mots de passe en clair, là où detect-secrets en trouve 13.

Pourquoi ce gain est un majorant

Le correctif a été écrit sans accès à la vérité terrain ni aux scores du banc. Mais la consigne donnée pour l'écrire citait les types de fichiers ratés au premier passage (dotfiles, id_rsa, .git-credentials, .s3cfg, .ppk). Il n'est donc pas indépendant de leaky-repo, et le passage de 4,5 % à 31,8 % sur ce corpus est un majorant de ce qu'on peut attendre ailleurs, pas une mesure indépendante. Détail qui va dans le même sens : le .git-credentials cité dans la consigne reste raté après correctif, comme chez les trois autres outils. En sens inverse, la règle PuTTY ajoutée répond elle-même au .ppk cité.

Ce qu'aucun des quatre ne voit

Si l'on additionne ce que trouvent detect-secrets, gitleaks, trufflehog et la passe corrigée de SecAI, sans compter deux fois une même ligne, on obtient 43 lignes sur 88 dans leaky-repo, soit 48,9 %, et 40 valeurs distinctes sur 83. La 43e, une clé Django, n'est trouvée que par la passe corrigée de SecAI ; sans elle, 42 lignes. Et sans la tolérance sur les en-têtes de clé privée, l'union tombe à 42 sur 88, la clé PuTTY n'étant alors plus créditée à personne. Les quatre réunis ratent donc 45 lignes. La répartition par type dit lesquelles.

angles morts
Lignes de leaky-repo trouvées par au moins un des quatre scanners, par type de secret
Lignes de leaky-repo trouvées par au moins un des quatre scanners, par type de secretClés privées3 sur 3100,0 %Clés d'API cloud7 sur 7100,0 %Jetons SaaS5 sur 5100,0 %Authentification de registre de paquets5 sur 683,3 %URL avec identifiants1 sur 250,0 %Mots de passe en clair13 sur 2748,1 %Mots de passe chiffrés ou encodés5 sur 1145,5 %Clés secrètes d'application4 sur 1428,6 %Hachages de mots de passe0 sur 130,0 %
Lignes de leaky-repo trouvées par au moins un des quatre scanners, par type de secret
CatégorieValeur (%)Précision
Clés privées100,03 sur 3
Clés d'API cloud100,07 sur 7
Jetons SaaS100,05 sur 5
Authentification de registre de paquets83,35 sur 6
URL avec identifiants50,01 sur 2
Mots de passe en clair48,113 sur 27
Mots de passe chiffrés ou encodés45,55 sur 11
Clés secrètes d'application28,64 sur 14
Hachages de mots de passe0,00 sur 13
Banc own2pwn du 6 octobre 2026. gitleaks 8.28.0, trufflehog 3.99.0, detect-secrets 1.5.0 et la passe regex et entropie de SecAI (worker SecretScanner, commits 6f9cb410 et de5bfb3), configurations par défaut, une exécution par outil, réseau coupé pour tous (passe SecAI après correctif). Union des vrais positifs des quatre outils, calculée à partir des listes de lignes détectées de results.json (clé leaky_repo_88) et des types de la vérité terrain. Une alerte n'est un vrai positif que si la valeur capturée contient le secret ; une alerte sur l'en-tête d'une clé privée est créditée.

Ce qui a une forme reconnaissable est trouvé : clés privées, clés cloud, jetons SaaS, tout est là. Ce qui n'a pas de forme passe. Les 13 hachages de mots de passe (bcrypt dans un dump SQL, sha512crypt dans un shadow, apr1 dans un .htpasswd) ne sont signalés par personne ; leaky-repo les compte comme des secrets, parce qu'un hachage s'attaque hors ligne, et que l'apr1 du .htpasswd est faible. Les clés secrètes d'application passent aussi : le master.key de Rails, l'APP_KEY de Laravel et les huit clés et sels de wp-config.php ne sont vus par aucun outil. Enfin la moitié des mots de passe en clair reste invisible, souvent parce qu'ils vivent dans des formats que les règles génériques ne lisent pas : .netrc, .pgpass, profils FileZilla et Robomongo. Même sort pour l'URL avec identifiants du .git-credentials.

Le lot fictif raconte la même chose en plus petit. Réunis, les quatre en trouvent 24 sur 25. Le seul raté commun est une clé Datadog écrite en 32 caractères hexadécimaux sans préfixe : sans motif distinctif, aucune règle ne la distingue d'un identifiant quelconque.

Ce que ça change pour votre outillage

Première conséquence : ne pas croire à un scanner unique. Le meilleur de leaky-repo est le pire du lot moderne, et l'inverse. Or ce que contient votre parc ressemble aux deux : des jetons à préfixe dans le code récent, des mots de passe et des dotfiles dans ce qui traîne depuis dix ans. Combiner un détecteur à mots-clés et un détecteur à motifs paie immédiatement : detect-secrets et gitleaks ensemble trouvent 42 des 43 lignes que les quatre outils trouvent à eux tous.

  • Deux détecteurs, de nature différente : un outil à motifs nommés comme gitleaks pour les jetons modernes, un outil à mots-clés et entropie comme detect-secrets pour les mots de passe et la vieille configuration. Le paramétrage de gitleaks, ses règles maison et son passage sur un dépôt complet sont détaillés dans détecter les secrets avec gitleaks. Le banc a utilisé la configuration par défaut de gitleaks, pas une configuration dédiée.
  • L'historique, pas seulement l'arbre : le banc n'a lu que les fichiers présents, alors qu'un secret supprimé vit encore dans le diff du commit qui l'a ajouté. Un scan de l'historique complet, au moins une fois puis à chaque push, est la seule façon de voir ce qui a déjà fui.
  • Le pre-commit et la push protection : un hook qui scanne le diff avant le commit arrête la fuite là où elle naît, et la push protection de GitHub refuse côté serveur un push contenant un secret reconnu. Les deux ne voient que ce que voient leurs règles, avec les angles morts mesurés plus haut.
  • Interdire ce qu'aucun outil ne voit : dumps SQL, .netrc, .pgpass, master.key, wp-config.php réel, profils FileZilla et .ftpconfig. Aucun scanner du banc ne les a lus correctement, donc la défense est en amont : un .gitignore strict, un refus de ces noms de fichiers dans le hook, et une relecture humaine quand ils apparaissent quand même.

Reste la couche qui rend le reste moins grave. Un vault (HashiCorp Vault, AWS Secrets Manager, un KMS) garde la valeur hors du code : le dépôt ne contient qu'une référence, injectée à l'exécution, et un secret qui n'est jamais dans le code ne peut pas fuiter par le code. La rotation part de l'hypothèse qu'un secret finira par fuiter et limite sa durée de vie : un jeton qui expire dans une heure vaut beaucoup moins qu'une clé statique valide depuis trois ans. Et le moindre privilège plafonne le coût : si le compte de coffre volé chez Uber n'avait ouvert qu'un périmètre, un seul secret n'aurait pas ouvert AWS, Slack et le reste d'un coup.

Répondre à une fuite : dans quel ordre agir

Le réflexe de beaucoup d'équipes, face à un secret exposé, est de foncer nettoyer l'historique Git pour faire disparaître la clé. C'est l'erreur classique. L'ordre correct n'est pas négociable, et si la clé a déjà servi à une intrusion, la réponse dépasse le seul secret : que faire en cas de piratage prend le relais.

reponse-fuite
Étape 4
Nettoyer l'historique
Réécriture Git, en dernier. Utile pour l'hygiène, jamais pour la sécurité.
Étape 3
Enquêter sur l'abus
Logs d'accès du fournisseur : la clé a-t-elle déjà servi ? Depuis où ?
Étape 2
Faire tourner (rotation)
Générer un nouvel identifiant, le déployer via un vault, pas en dur.
Étape 1
RÉVOQUER le secret
Invalider la clé côté fournisseur. C'est la seule action qui coupe l'accès.
Révoquer d'abord, nettoyer ensuite. L'inverse laisse la clé vivante pendant que vous perdez du temps sur l'historique.

La révocation invalide le secret chez le fournisseur, donc même l'attaquant qui l'a copié se retrouve avec une clé morte. Réécrire l'historique avec git-filter-repo ou BFG ne nettoie que votre copie : forks, clones, cache de la plateforme, vues de pull request et copies des bots gardent la valeur. Le réécriture évite qu'une clé morte pollue vos audits futurs, il ne sécurise rien.

bash
# NON. Ceci ne protège rien tant que la clé n'est pas révoquée :
git filter-repo --replace-text secrets.txt   # nettoie VOTRE historique...
git push --force                              # ...mais forks, clones, caches gardent la clé

# L'ordre qui compte :
# 1) Révoquer la clé dans la console du fournisseur (AWS/Stripe/GitHub...)
# 2) Émettre une nouvelle clé, la charger depuis un vault
# 3) Lire les logs d'accès : la clé a-t-elle été utilisée ?
# 4) SEULEMENT ENSUITE, réécrire l'historique pour l'hygiène

Détecter en continu, depuis l'extérieur

Les scanners du banc couvrent ce que vous maîtrisez : vos dépôts, vos pipelines. Le cas Toyota rappelle qu'une grande partie de l'exposition vit ailleurs, chez un sous-traitant, sur un compte perso, dans un bundle livré à tous les navigateurs, dans un bucket que personne n'a inventorié. Notre module de détection de fuites et de secrets part d'un domaine et remonte les dépôts Git exposés, les fichiers .env et configurations accessibles sans authentification, les buckets ouverts et les endpoints qui divulguent des secrets, en continu. Côté code, la passe mesurée ici tourne dans SecAI, l'analyse de sécurité applicative, avec les limites que vous venez de lire.

Les secrets dans le code ne sont qu'une moitié du problème d'identifiants. L'autre, ce sont les comptes de vos employés qui ressortent dans les fuites grand public, souvent avec un mot de passe compromis réutilisé côté pro, puis rejoués en masse sur vos formulaires de connexion par credential stuffing. Pour une adresse, un service comme Have I Been Pwned suffit ; pour une organisation, il faut suivre tout le domaine, y compris par une surveillance du dark web où ces identifiants se revendent parfois des mois avant d'être utilisés. Tout cela suppose d'abord une découverte des actifs exposés : on ne cherche des secrets que sur une surface cartographiée. Et quand un secret ouvre une compromission plus profonde, mesurer jusqu'où elle mène relève du pentest web blackbox.

Les limites de ce banc

Ces chiffres valent pour ces corpus, ces versions et ces réglages, ce jour-là. Ce qui en limite la portée :

  • leaky-repo date de 2020 : beaucoup de mots de passe en clair et de hachages, peu de formats modernes à préfixe. Il favorise les outils à mots-clés et pénalise les détecteurs nommés. Et 88 lignes retenues contre 96 annoncées par son CSV : la vérité terrain est un jugement humain, documenté ligne par ligne, qu'on peut contester.
  • Le lot fictif est écrit pour le banc, presque toujours au format NOM=valeur avec des noms explicites (OPENAI_API_KEY, NPM_TOKEN...), ce qui favorise les règles génériques mot-clé et entropie : 9 des 20 lignes trouvées par la passe de SecAI viennent de sa règle générique, pas d'une règle nommée. Son jeton PyPI a le bon préfixe mais n'est pas un macaron valide, donc trufflehog, qui décode le macaron, le rejette à raison. Il mesure une couverture de formats, pas un rappel en conditions réelles.
  • La précision ne discrimine presque rien : deux corpus saturés de secrets, quasiment sans leurres. Les 100 % affichés ne disent rien du bruit sur un vrai dépôt, en particulier pour la règle générique élargie de SecAI : 24 des 29 alertes de la passe corrigée de SecAI sur leaky-repo viennent de cette règle générique.
  • Le correctif de SecAI a été guidé par ce corpus : il l'a été par les types de fichiers ratés sur ce même corpus, donc son gain sur leaky-repo n'est pas une mesure indépendante.
  • Une exécution par outil, en configuration par défaut : gitleaks a par exemple une configuration dédiée qui n'a pas été utilisée. Les durées ont été consignées mais ne sont pas comparables, donc pas publiées.
  • Réseau coupé pour tous : aucune vérification de validité, ce qui retire à trufflehog et detect-secrets un mécanisme qu'ils ont en production et qui, ici, ne fait baisser le rappel d'aucun des deux. Et un seul arbre de fichiers, sans historique git.

À retenir

  • Un secret publié est essayé vite : une clé AWS leurre exposée sur GitHub a servi en deux minutes dans le banc d'Orca Security.
  • Le classement des scanners de secrets s'inverse selon le corpus : detect-secrets premier sur leaky-repo (40,9 %), dernier sur les jetons modernes (68 %) ; gitleaks l'inverse (23,9 % et 92 %).
  • Réunis, les quatre outils trouvent 43 lignes sur 88 de leaky-repo. Aucun ne voit les hachages, les clés secrètes d'application ni la moitié des mots de passe en clair.
  • La passe regex et entropie de SecAI est passée de 4,5 % à 31,8 % après correctif, un gain majorant et non indépendant, et reste derrière detect-secrets sur leaky-repo.
  • Deux détecteurs de nature différente, l'historique scanné, les fichiers sensibles interdits en amont, puis en cas de fuite on révoque d'abord et on nettoie ensuite.

Vous voulez savoir quels secrets de votre organisation traînent déjà quelque part d'accessible ? C'est ce que cherche notre module de détection de secrets exposés, en continu et du point de vue d'un attaquant. Pour en parler avec un pentester, passez par la page contact.

Questions fréquentes

Qu'est-ce qu'une fuite de secrets ?

C'est l'exposition d'une donnée d'authentification (clé d'API, token, mot de passe de base de données, clé privée SSH) hors de son coffre. Il n'y a rien à exploiter : celui qui détient le secret devient l'application ou l'utilisateur légitime.

Quel scanner de secrets détecte le plus de fuites ?

Ça dépend du corpus. Sur un banc own2pwn du 6 octobre 2026, avec la même règle de comptage pour tous et le réseau coupé, detect-secrets 1.5.0 arrive en tête sur leaky-repo (40,9 % des 88 lignes porteuses d'un secret), un vieux dépôt plein de mots de passe et de fichiers de configuration, mais en dernier sur un lot de 25 jetons modernes à préfixe (68 %). gitleaks 8.28.0 fait l'inverse : 23,9 % sur leaky-repo, 92 % sur le lot de jetons. trufflehog 3.99.0 obtient 9,1 % et 76 %. La passe regex et entropie de SecAI, notre produit, obtient 31,8 % et 80 % après un correctif, un gain non indépendant de ce corpus, et reste derrière detect-secrets sur leaky-repo.

Un scanner de secrets suffit-il ?

Non. Sur ce même banc, les quatre outils réunis ne trouvent que 43 des 88 lignes de leaky-repo. Aucun ne signale les 13 hachages de mots de passe, et ils ratent ensemble 14 mots de passe en clair sur 27 et 10 clés secrètes d'application sur 14. Combiner un détecteur à mots-clés et un détecteur à motifs couvre presque tout ce que les quatre trouvent (42 lignes sur 43), mais le reste demande d'interdire ces fichiers dans les dépôts et de les relire.

J'ai commité une clé d'API par erreur, que faire en premier ?

Révoquer la clé chez le fournisseur, avant tout le reste. Générez-en une nouvelle, mettez à jour les services qui l'utilisent, lisez les journaux d'accès du fournisseur, puis seulement ensuite effacez le secret de l'historique Git. Nettoyer d'abord ne sert à rien : forks, clones et caches en gardent une copie. Seule la révocation coupe réellement l'accès.

Supprimer un secret de l'historique Git suffit-il à le sécuriser ?

Non. Réécrire l'historique avec git-filter-repo retire le secret de votre dépôt, mais toute personne qui a cloné, forké ou mis en cache la version exposée en garde une copie. Considérez tout secret poussé sur un dépôt comme compromis : la seule réponse fiable reste de le révoquer et de le remplacer.

Comment détecter les secrets exposés de mon entreprise ?

Sur deux périmètres. En interne, un hook pre-commit et un scan des dépôts, historique compris, avec deux détecteurs de nature différente plutôt qu'un. En externe, une détection continue qui part de votre domaine et remonte dépôts publics, bundles JavaScript, fichiers .env accessibles et buckets ouverts, y compris chez des sous-traitants ou sur des comptes personnels d'employés, là où aucun audit interne ne regarde.

Veille sécurité

La suite, une fois par mois

Ce qui bouge vraiment sur la surface d'attaque externe, NIS2 et la sécurité applicative, écrit par le pentester qui signe ces articles. Un envoi par mois, désinscription en un clic.

Votre adresse ne sert qu'à cet envoi. Voir la politique de confidentialité.