Outils IA

Fuzzing par agent IA : le Taskflow Agent de GitHub en pratique

Fuzzing par agent IA : le Taskflow Agent de GitHub pilote AFL++, trie les crashs et propose un correctif. Architecture, limites et leçons pour vos agents.

Fuzzing par agent IA : le Taskflow Agent de GitHub en pratique

Fuzzing par agent IA : le Taskflow Agent de GitHub en pratique

Le fuzzing par agent IA vient de franchir un cap concret. Le 24 septembre 2026, le GitHub Security Lab a publié le Taskflow Agent de fuzzing, un pipeline open source où un modèle de langage choisit quoi fuzzer, écrit les harnais, lit les rapports de couverture, trie les crashs et propose un correctif. On lui donne un seul paramètre, le nom d'un dépôt GitHub au format owner/repo, et il enchaîne le reste.

Pourquoi ça compte maintenant pour les équipes qui industrialisent du logiciel et de l'IA ? Parce que le goulot du fuzzing n'a jamais été la puissance de calcul. C'est l'attention humaine : surveiller la couverture, écrire de nouveaux harnais quand elle stagne, trier des centaines de crashs dont la plupart sont des artefacts. Le projet de GitHub s'attaque précisément à cette partie, et la façon dont il le fait est un bon modèle pour quiconque conçoit des agents qui touchent à la production.

Le contexte

Le fuzzing consiste à bombarder un programme d'entrées générées automatiquement, souvent malformées, pour provoquer des comportements inattendus : plantage, fuite mémoire, boucle infinie. Un harnais (fuzz target) est le petit programme qui prend ces octets et les passe à la fonction testée. La couverture mesure quelles lignes et quelles branches du code ces entrées ont réellement atteintes.

Les outils sont matures. AFL++ guide la génération d'entrées en observant les branches parcourues, AddressSanitizer détecte les accès mémoire invalides au moment où ils se produisent. Ce qui manque, c'est l'opérateur. L'auteur du projet, Antonio Morales, le résume ainsi : « le fuzzing continu n'est pas une solution magique qui règle tous vos problèmes ». Des projets fuzzés depuis des années dans OSS-Fuzz cachent encore des bugs critiques, parce que personne n'a relu la couverture ni écrit le harnais qui manquait.

C'est ce travail d'opérateur, répétitif et exigeant, que le Taskflow Agent confie à un modèle de langage.

Une architecture en trois couches qui sépare décision et exécution

Le système est construit en trois couches. Un script shell pilote l'ensemble du pipeline. Des fichiers de configuration YAML, les taskflows, contiennent les instructions données à l'agent à chaque étape. Enfin, des outils MCP exécutent le travail réel : compiler, lancer le fuzzer, produire les rapports.

Le principe directeur est énoncé noir sur blanc : l'agent LLM possède les décisions, les outils MCP possèdent l'exécution. L'agent décide quoi fuzzer et quelle zone non couverte attaquer. Les outils compilent et exécutent. Tout l'état persistant vit dans une base SQLite, pas dans la mémoire de l'agent ni dans des transferts implicites entre étapes.

Pourquoi cette séparation est la bonne

C'est le point le plus transposable du projet. Un agent qui raisonne et un outil déterministe qui agit, avec un état stocké hors du modèle, donnent trois propriétés que toute équipe MLOps recherche : les étapes sont rejouables, les erreurs sont localisables (on sait si c'est la décision ou l'exécution qui a échoué) et une campagne interrompue reprend là où elle s'était arrêtée. C'est la même discipline que l'on applique à un pipeline de données, appliquée à un agent.

Chaque harnais est compilé deux fois : une fois avec afl-clang-lto pour guider le fuzzing, une fois avec clang -fprofile-instr-generate -fcoverage-mapping pour produire un rapport de couverture lisible. Le premier binaire sert la machine, le second sert le raisonnement de l'agent et la lecture humaine.

La boucle de couverture, cœur du fuzzing par agent IA

La vraie nouveauté n'est pas de lancer AFL++ : c'est de le relancer intelligemment. Le pipeline tourne en boucle :

  1. lancer AFL++ pendant un budget de temps ;
  2. rejouer la file d'entrées générées sur le binaire instrumenté pour obtenir la couverture réelle ;
  3. analyser les branches non couvertes ;
  4. choisir une stratégie pour les atteindre, puis recommencer.

Les budgets croissent de façon géométrique : 30 s, 60 s, 120 s, 240 s, 480 s, 960 s, soit environ 32 minutes par cible. On dépense peu tant que les gains faciles existent, et on réserve les longues exécutions aux zones difficiles. La boucle s'arrête sur un plateau : quand deux itérations consécutives gagnent chacune moins d'un seuil configurable, 1 % de couverture de lignes en valeur absolue par défaut, l'agent passe à la suite.

Des entrées qui comprennent le format

Pour atteindre le code profond d'un parseur, des octets aléatoires ne suffisent pas. Le pipeline combine quatre mécanismes :

  • des dictionnaires AFL et des mutateurs dédiés pour les formats reconnus (JSON, XML, expressions régulières, PNG, TLV préfixé par sa longueur) ; le mutateur XML connaît par exemple les balises, les entités et les jetons de type billion laughs ;
  • des mutateurs générés à la volée pour les formats inconnus, à partir des chaînes littérales et des constantes numériques extraites du code source, c'est-à-dire les « valeurs magiques » que le parseur vérifie ;
  • des dictionnaires enrichis après chaque itération avec les constantes trouvées près des lignes encore non couvertes ;
  • un opérateur qui recombine des fichiers du corpus existant.

Le corpus, lui, n'est jamais jeté. Chaque harnais possède un répertoire stable, fusionné après chaque itération puis réduit avec afl-cmin. Une campagne de la semaine prochaine démarre donc avec tout ce que celle d'aujourd'hui a appris.

Du crash au correctif : un tri qui fait gagner des jours

La partie la plus chronophage du fuzzing a toujours été le tri. Ici, chaque crash est minimisé avec afl-tmin, rejoué sous AddressSanitizer pour obtenir une pile d'appels, puis dédupliqué par le haut de la pile. Les crashs déjà connus sont rejoués sur les binaires à jour pour vérifier si un correctif amont les a résolus.

L'agent attribue ensuite un verdict parmi sept : vulnérabilité, durcissement de la bibliothèque, bug du harnais, manque de mémoire, timeout, échec d'assertion ou doublon. Distinguer une vraie vulnérabilité d'un artefact de test suppose de savoir si le code fautif est atteignable depuis l'API publique, un travail qui demandait jusqu'ici une lecture manuelle du code.

Pour chaque cas, le rapport contient une analyse de cause racine avec des références fichier:ligne, un argument d'atteignabilité, une évaluation d'exploitabilité, un correctif proposé sous forme de diff unifié et une ébauche de test de régression. Le tout est marqué « revue requise ». Un tableau de bord HTML, lancé sur le port 8765, montre en direct la couverture par harnais, une carte des crashs et la chronologie des itérations.

Le modèle par défaut est Claude Sonnet 5, retenu parce qu'il a passé tous les tests internes de l'équipe ; il se change dans un fichier de configuration. Le code est public sur le dépôt seclab-taskflows-fuzzing, et le plus simple pour l'essayer est un Codespace ouvert sur ce dépôt.

Les limites à lire avant de brancher ça sur votre CI

L'article de GitHub est honnête sur deux points qu'il ne faut pas survoler.

L'agent se trompe

« L'analyse de l'agent est limitée par la compréhension que le modèle a du code cible, et il se trompe. » Les verdicts sont présentés comme un point de départ très bien préparé pour un humain, pas comme un résultat final. Concrètement : un verdict « vulnérabilité » doit être confirmé par quelqu'un qui connaît le code, et un diff proposé reste une proposition.

Il exécute ce qu'il décide, sans conteneur

C'est la mise en garde la plus importante. Le pipeline exécute afl-fuzz, clang et des commandes de build arbitraires choisies par le LLM directement sur la machine hôte, sans conteneur intermédiaire. La consigne est explicite : ne le lancer que dans un environnement jetable, un Codespace ou une machine virtuelle à usage unique, sans privilèges élevés.

L'article ne publie pas non plus de chiffres de résultats (nombre de vulnérabilités trouvées, comparaison avec un fuzzing manuel) ni de coût d'inférence. Une campagne de plusieurs cibles à 32 minutes chacune, avec des appels de modèle à chaque itération, n'est pas gratuite : mesurez-la sur un projet pilote avant de la généraliser.

Ce que ça change pour les équipes IA

Au-delà de la sécurité C/C++, ce projet est une démonstration de ce qu'est un agent industrialisable. Quatre leçons s'appliquent directement à vos propres pipelines.

1. Séparer décision et exécution. Le modèle choisit, des outils déterministes exécutent, un état externe fait foi. C'est ce qui rend un agent débogable, et c'est le même patron que celui que nous recommandons pour les agents RAG ou les agents d'exploitation : le LLM ne doit jamais être la seule mémoire du système.

2. Budgéter le temps comme une ressource. La progression géométrique et la détection de plateau sont une réponse simple au problème classique des agents qui bouclent. Un agent de production a besoin d'un critère d'arrêt mesurable, pas d'une consigne « arrête-toi quand c'est fini ».

3. Isoler par défaut. Un agent qui génère et exécute des commandes doit tourner dans un bac à sable éphémère, sans secrets de production, sans privilèges, avec un réseau restreint. Dans une CI, cela veut dire un runner dédié et jetable, pas le runner partagé qui a accès à vos registres et à vos clés cloud.

4. Garder l'humain au bon endroit. L'humain ne relit plus chaque crash : il valide les verdicts de vulnérabilité et les correctifs. C'est le bon partage. Il se traduit dans un pipeline par une étape d'approbation explicite, pas par une revue facultative que personne ne fait.

Pour une équipe qui maintient une bibliothèque de parsing, un format de fichier maison ou un composant natif exposé à des entrées externes, le fuzzing par agent IA devient accessible sans spécialiste du fuzzing à plein temps. Commencez par une campagne ponctuelle dans une VM jetable, mesurez la couverture gagnée et le temps de tri économisé, puis décidez s'il mérite une place dans votre CI nocturne. Pour les bases, GitHub renvoie à son cours Fuzzing 101.

En bref

  • Le GitHub Security Lab publie un pipeline open source où un agent LLM pilote AFL++ de bout en bout, à partir d'un simple owner/repo.
  • L'architecture sépare décision (l'agent) et exécution (outils MCP), avec un état SQLite rejouable.
  • Une boucle de couverture à budgets géométriques et arrêt sur plateau remplace la surveillance humaine.
  • Le tri produit verdict, cause racine, atteignabilité et diff de correctif, marqués « revue requise ».
  • À exécuter uniquement dans un environnement jetable : l'agent lance des commandes de build de son choix sur l'hôte.

Vous industrialisez vos agents IA ? SeedVision propose des audits IA en 3-5 jours et des forfaits de mise en production de 15 à 30 jours. Voir les packages ou réserver un appel de 30 min.

Photo de couverture : Photo by Chris Ried on Unsplash.