29 millions de secrets sur GitHub : ce que l'IA change aux fuites de clés
par detektd team

Chaque année, GitGuardian analyse l'ensemble des commits publics de GitHub pour y compter les secrets (clés d'API, jetons, mots de passe, chaînes de connexion) écrits en clair. L'édition 2026 de son rapport State of Secrets Sprawl, publiée en mars, couvre l'année 2025 : 1,94 milliard de commits publics (+43 %), et 28,65 millions de nouveaux secrets exposés, soit +34 % sur un an. C'est la plus forte hausse jamais mesurée par l'entreprise.
secrets écrits en clair dans des commits publics GitHub en 2025, +34 % sur un an (GitGuardian, mars 2026)
L'IA, première source de croissance
Le chiffre le plus marquant concerne les services d'IA. GitGuardian a détecté 1 275 105 secrets liés à des fournisseurs d'IA en 2025, en hausse de 81 %. Huit des dix types de secrets qui progressent le plus vite concernent l'IA ; à eux seuls, plus de 113 000 clés d'API DeepSeek ont été exposées. Et l'infrastructure autour des modèles (passerelles, bases vectorielles, outils d'orchestration) fuit cinq fois plus vite que les clés des grands fournisseurs de modèles eux-mêmes.
Le rapport s'est aussi intéressé au code écrit avec des assistants. Sur les commits identifiables comme assistés par Claude Code, le taux de commits contenant un secret atteint 3,2 %, contre 1,5 % en moyenne sur GitHub public. GitGuardian prend soin de le préciser : c'est le développeur qui accepte ou refuse la suggestion. Mais le mécanisme est facile à reconstituer. Quand on demande à un agent de « faire marcher » une intégration, la voie la plus directe consiste à mettre la clé là où le code en a besoin.
Nouveau venu dans les chiffres : les fichiers de configuration MCP, qui décrivent les outils branchés à un assistant (.cursor/mcp.json, .vscode/mcp.json, claude_desktop_config.json...). GitGuardian y a trouvé 24 008 secrets uniques sur GitHub public, dont 2 117 encore valides. En cause, selon le rapport : une documentation qui montre souvent la clé directement dans le fichier, lequel finit committé avec le reste du projet.
Comment une clé finit dans le navigateur
Un secret committé dans un dépôt public est grave. Un secret embarqué dans le JavaScript servi aux visiteurs l'est tout autant, et ce second chemin est spécifique au développement web moderne. Les bundlers remplacent certaines variables d'environnement par leur valeur au moment du build, et le résultat est un fichier que n'importe quel visiteur télécharge.
La règle est la même partout, seul le préfixe change. Dans Next.js, toute variable préfixée NEXT_PUBLIC_ est inlinée dans le bundle client. Dans Vite, c'est VITE_, via import.meta.env. Dans Create React App, REACT_APP_. Ces préfixes existent précisément pour marquer ce qui peut être public. Le piège est de préfixer une clé serveur « parce que sinon ça ne marche pas côté client », c'est-à-dire exactement le correctif qu'un agent pressé propose quand un appel échoue dans le navigateur.
# .env.local NEXT_PUBLIC_SUPABASE_URL=... # inlined: public by design, fine NEXT_PUBLIC_OPENAI_API_KEY=sk-... # inlined: every visitor can read it OPENAI_API_KEY=sk-... # server-only: never reaches the browser
Next.js fournit un garde-fou pour l'erreur inverse : importer un module serveur dans un composant client. En ajoutant import "server-only" en tête d'un fichier qui manipule des secrets, toute tentative de l'importer côté client fait échouer le build au lieu d'embarquer silencieusement son contenu.
import "server-only";
export async function complete(prompt: string) {
const res = await fetch("https://api.openai.com/v1/responses", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.OPENAI_API_KEY}` },
body: JSON.stringify({ model: "gpt-5", input: prompt }),
});
return res.json();
}Comment les détecteurs trouvent une clé
La détection moderne des secrets repose sur trois couches. D'abord, les préfixes : la plupart des fournisseurs donnent à leurs clés une forme reconnaissable, précisément pour faciliter leur détection : AKIA pour un identifiant de clé AWS, ghp_ pour un jeton personnel GitHub, sk_live_ pour une clé secrète Stripe, xoxb- pour un jeton de bot Slack. Ensuite, l'entropie : une chaîne aléatoire de 40 caractères ne ressemble pas à un mot. Enfin, la validation : un détecteur sérieux vérifie, quand le fournisseur le permet, si la clé est encore active, ce qui sépare une fuite historique d'un incident en cours.
Le rapport pointe une limite de cette dernière couche : prioriser uniquement les secrets validés fait passer à côté de 46 % des secrets critiques. Beaucoup de clés ne peuvent tout simplement pas être testées de l'extérieur (identifiants de bases internes, clés de services auto-hébergés), et ce sont souvent les plus sensibles.
Le vrai problème : personne ne révoque
Le chiffre le plus inquiétant du rapport n'est pas celui des fuites, mais celui des corrections : 64 % des secrets valides détectés en 2022 l'étaient encore en janvier 2026. Supprimer le fichier, ou même réécrire l'historique Git, ne sert à rien si la clé reste active. Un commit public est cloné, mis en cache et indexé en quelques minutes ; la seule correction réelle est la révocation.
des secrets valides détectés en 2022 étaient toujours actifs en janvier 2026 (GitGuardian)
Les dépôts publics ne sont d'ailleurs pas le pire endroit. Les dépôts internes sont six fois plus susceptibles de contenir des secrets, et 28 % des incidents naissent hors du code : Slack, Jira, Confluence, où ces fuites ont 13 points de plus de chances d'être critiques. Le rapport analyse aussi les machines compromises par la deuxième vague du ver Shai-Hulud : 6 943 machines, 33 185 secrets uniques, et 59 % d'entre elles étaient des runners CI/CD, pas des postes de développeurs.
Une chaîne de défense en quatre maillons
- Avant le commit : un hook pre-commit (gitleaks, ggshield) et la protection au push de GitHub, qui bloque un push contenant un secret reconnu.
- Dans le code : aucune clé serveur derrière un préfixe public, import "server-only" sur les modules sensibles, et des références à des variables d'environnement dans les configs MCP plutôt que des valeurs.
- En production : vérifier ce que le site sert réellement (bundles, fichiers exposés), puisque c'est ce que voit un attaquant, quel que soit l'état du dépôt.
- Après une fuite : révoquer d'abord, nettoyer ensuite. Et remplacer autant que possible les clés longues durées par des identifiants courts (OIDC en CI, jetons temporaires).
Le troisième maillon est celui que detektd couvre. À chaque scan, les bundles JavaScript réellement servis par l'app sont analysés à la recherche de clés reconnaissables (fournisseurs d'IA, Stripe, AWS, services tiers), et les fichiers qui ne devraient jamais être publics (.env, sauvegardes, configurations) sont vérifiés à la racine du site.

16 326 bases Supabase lisibles par n'importe qui
Une étude UpGuard publiée le 25 septembre 2026 a trouvé 16 326 bases Supabase aux tables lisibles par n'importe qui, sans authentification ni exploit. La cause tient en une phrase : le Table Editor protège par défaut, l'API que les agents IA utilisent ne le fait pas.

21 000 serveurs MCP exposés sur Internet : pourquoi l'authentification est « optionnelle »
Censys a compté plus de 12 500 serveurs MCP joignables depuis Internet en avril, puis plus de 21 000 en mai. Une étude publiée fin juillet a audité 414 d'entre eux : 91,8 % sans authentification OAuth. Comment le protocole fonctionne, et comment on en arrive là.