J'ai construit un outil qui trouve des bugs dans Kubernetes, gVisor et les outils de la NASA
Je viens du réseau et du support : une licence en administration des réseaux et télécoms, puis un poste de technicien support chez Apple. Aujourd'hui, des mainteneurs de Kubernetes, de Google et de Canonical ont validé des correctifs que je leur ai proposés, et d'autres sont en revue chez Prometheus, à la NASA et chez data.gouv.fr.
Entre les deux, j'ai construit un outil : GitHub Security Researcher (GSR). Voici comment il fonctionne, ce qu'il a trouvé, et ce que j'en ai appris.
Le problème : trop d'alertes, pas assez de bugs
Les analyseurs de code produisent des centaines d'alertes plausibles. La plupart sont des faux positifs. Et depuis l'arrivée des LLM, c'est pire : une IA peut affirmer avec aplomb qu'un bout de code est vulnérable… ou se laisser manipuler par un commentaire planté dans le code qu'elle lit.
Proposer ces alertes à des mainteneurs bénévoles, c'est leur faire perdre leur temps. Je voulais l'inverse : peu de résultats, mais des vrais.
Le principe : l'IA propose, les tests décident
GSR est un outil en ligne de commande en Python. Son pipeline sépare quatre étapes :
- Détection : des scanners et des détecteurs statiques repèrent des sites suspects.
- Analyse contextuelle : un LLM peut donner son avis, mais cet avis est stocké comme simple indice.
- Preuves : chaque résultat accumule des preuves typées (flux de données, contexte de code, résultat de test…).
- Décision : un moteur déterministe tranche entre
CONFIRMED,FALSE_POSITIVEetINCONCLUSIVE.
La règle centrale est inscrite dans le code et dans les tests : une analyse par LLM seule ne peut jamais produire CONFIRMED. En cas de doute, le verdict est INCONCLUSIVE.
L'outil traite aussi le contenu des dépôts analysés comme des données non fiables : il n'exécute jamais leur code, et le LLM tourne sans aucun outil, avec le contenu du dépôt encadré pour qu'il ne puisse pas être pris pour des instructions.
Des détecteurs pour de vrais bugs Go
Une grande partie du travail a été d'écrire des détecteurs pour des familles de bugs précises dans du code Go, en analysant la syntaxe avec tree-sitter. Par exemple, un motif qui revient très souvent dans les parseurs :
parts := strings.SplitN(line, "=", 2)
key, value := parts[0], parts[1] // panic si la ligne ne contient pas "="
Si la ligne lue ne contient pas le séparateur, parts n'a qu'un élément et le programme plante. Le détecteur repère ces accès, puis cherche une preuve qu'ils sont protégés : une vérification de longueur avant l'accès, un test de présence du séparateur, une sortie anticipée… Un accès protégé est écarté, avec la preuve de sa protection.
D'autres familles sont venues de bugs réels : une vérification de longueur écrite après l'accès qu'elle devait protéger, une erreur de verrouillage ignorée suivie d'un déverrouillage qui peut paniquer, une valeur testée à nil avant que l'erreur qui l'accompagne soit lue.
Chaque correction du détecteur passe par des tests : l'outil en compte aujourd'hui plus de 500.
Trois bugs, trois histoires
Kubernetes : un plantage sur une configuration git
Le premier bug a été trouvé dans git-sync, un outil de l'écosystème Kubernetes : une clé de configuration git sans valeur faisait planter le programme. Test de reproduction, correctif, test de régression : la PR a été fusionnée (#1006).
NASA : un fusionneur de code qui refusait du C++ valide
F´ (F Prime) est le framework de logiciel de vol de la NASA. Son outil fprime-util impl --auto-merge fusionne du code C++ généré avec le code écrit à la main, avec une règle d'or : ne jamais supprimer de code humain.
Pour vérifier cette règle, j'ai écrit un test de propriétés : générer des milliers de corps de fonctions C++ et vérifier qu'après fusion, chaque ligne existante est toujours là. Sur 3 000 cas, aucune ligne n'était perdue. Mais du C++ parfaitement valide faisait échouer la fusion : une chaîne brute contenant un guillemet (R"(say "hi)") ou un séparateur de chiffres (1'000). Le lexeur prenait l'apostrophe pour le début d'un caractère et perdait le fil des accolades.
J'ai ouvert une issue, puis proposé un correctif avec six tests (PR #356, en revue).
data.gouv.fr : 17 mai 2020 devenait « toute l'année 2020 »
udata est le logiciel derrière data.gouv.fr. Lorsqu'il moissonne des catalogues de données, il lit des dates de couverture temporelle. Pour savoir si une date désigne un jour, un mois ou une année, il comptait… les tirets. Résultat : 2020/05/17 ou 20200517 étaient interprétés comme l'année 2020 entière, sans aucun message d'erreur.
Le correctif détecte les parties réellement présentes dans la date au lieu de compter les séparateurs (issue #4006, PR #4007, en revue).
Les résultats
| Projet | Statut |
|---|---|
| Kubernetes git-sync #1006 | fusionnée |
| Google gVisor #15632 | approuvée par un mainteneur |
| Canonical LXD #19250 | approuvée par un mainteneur |
| NASA F´ fprime-tools #356 | en revue |
| data.gouv.fr udata #4007 | en revue |
| Prometheus node_exporter #3848, procfs #880, mysqld_exporter #1095 | en revue |
| Google cAdvisor #3947, Kubernetes kube-state-metrics #3143 | en revue |
Ce sont des bugs fonctionnels et de robustesse, pas des failles de sécurité. La plupart ont été trouvés avec les détecteurs de GSR, les autres par relecture ciblée, fuzzing ou tests de propriétés.
Ce que j'ai appris
Reproduire d'abord. Un motif suspect n'est pas un bug. Tant qu'un test n'échoue pas, je ne propose rien. Beaucoup de pistes prometteuses se sont révélées protégées, irréalistes ou déjà corrigées.
Chercher les doublons. Mon premier bug sur kube-state-metrics était déjà signalé. Depuis, chaque correctif passe par une vérification : le bug est-il toujours là sur la branche principale, une PR ouverte le corrige-t-elle déjà ?
Lire les règles de chaque projet. CLA à signer, Signed-off-by à ajouter soi-même, commits signés cryptographiquement, issue obligatoire avant la PR, déclaration de l'usage de l'IA… Chaque projet a ses règles, et les respecter compte autant que le code.
Utiliser l'IA comme un outil, pas comme un juge. J'ai développé GSR avec Claude Code, qui m'a fait gagner un temps énorme. Mais c'est toujours un test qui confirme un bug, jamais une IA.
Le code
GSR est open source, sous licence Apache-2.0 : https://github.com/LemonCondor/github-security-researcher
Mon site : https://lemoncondor.github.io/guillaume-marty/
Je cherche aujourd'hui un poste en développement Python et IA appliquée, à La Rochelle ou à distance. Si ce travail vous parle, écrivez-moi.