Cybersécurité

Votre framework d’agents est la surface d’attaque

Une issue GitHub ouverte par un inconnu a suffi à exécuter du code et à voler des secrets via Claude Code, Gemini CLI et Codex. En cause : pas le modèle, mais le code autour.

Une main glisse un billet plié dans la fente d’entrée d’une petite machine faite de tuyaux et de leviers, construite autour d’un cœur lumineux.

Les vulnérabilités relevées par Novee

AgentCause profondeIdentifiantRéponse de l’éditeur
Claude Code (GitHub Action) – tour 1Le validateur de commandes supprimait les chaînes entre guillemets simples avant la vérification ; git push --receive-pack=<payload> passait la validation et s’exécutait sur le runner—Corrigé
Claude Code – tour 2Le correctif reposait sur une liste d’autorisation codée en dur de commandes « en lecture seule », exemptées des contrôles réservés aux écritures ; lecture de fichiers sans restriction et exfiltration—Corrigé
Claude Code – tour 3Accès préapprouvé à Hugging Face détourné en canal d’exfiltration via les compteurs de téléchargements publicsCVE-2026-54316Corrigé
Gemini CLIContournement des restrictions d’exécution ; exécution de commandes système avant l’application du bac à sableCVE-2026-12537Corrigé
CodexDeux passes d’un même job de CI partagent le même checkout du dépôt ; la première écrit AGENTS.md, que la seconde charge comme des instructions faisant autoritéAucun attribuéOpenAI : choix de conception, pas une vulnérabilité

La chaîne git push --receive-pack mérite qu’on s’y arrête, justement parce qu’elle est d’une grande banalité. L’option receive-pack de Git permet à un push d’indiquer un programme à exécuter côté réception. D’après l’analyse de la Cloud Security Alliance, le validateur de Claude Code supprimait les chaînes entre guillemets simples avant d’appliquer ses contrôles : une charge utile cachée dans cette option passait donc intacte et s’exécutait sur le runner GitHub Actions. Exposition : GITHUB_TOKEN et ANTHROPIC_API_KEY, présents dans l’environnement du workflow. Avec un jeton GitHub doté de droits d’écriture, cela va jusqu’à la modification des workflows et à la publication de paquets sous l’espace de noms du dépôt – une compromission de la chaîne d’approvisionnement à partir d’une seule issue.

Les notes de recherche de la CSA disent clairement l’essentiel : ces chaînes exploitaient des lacunes de conception dans la validation des commandes et l’isolation des processus, et non la persuasion du modèle. Un modèle parfaitement aligné aurait été tout aussi exploitable, parce que c’est le harness qui traitait mal la sortie du modèle. Meged : « Le harness est le code entre le modèle et le monde réel » – et il « a échoué à maintes reprises à empêcher des contenus GitHub non fiables d’atteindre des environnements d’exécution privilégiés ».

Le cas Codex est le plus intéressant sur le plan conceptuel, car il s’agit d’un désaccord sur ce qui constitue une vulnérabilité. Position d’OpenAI : si vous configurez deux passes pour qu’elles partagent un espace de travail, le fait que la première écrive un fichier d’instructions auquel la seconde se fie correspond au comportement documenté du fichier AGENTS.md, et non à une faille. Position de Novee : un attaquant extérieur sans privilèges peut amener la première passe à écrire ce fichier. Les deux ont raison, et c’est précisément pour cela que « le framework est la vulnérabilité » est la bonne grille de lecture : le bug se loge dans la composition, pas dans la spécification d’un composant pris isolément.

Vulnérabilités au niveau des frameworks

La seconde présentation a fait descendre la surface d’attaque sous la couche des outils. La thèse : une logique exploitable au cœur du runtime de LangChain, CrewAI, AutoGen et Semantic Kernel.

  • Stockage de la mémoire. Un contenu injecté qui persiste dans la mémoire de l’agent est rejoué comme contexte de confiance lors des tours et des sessions suivants. C’est la vulnérabilité AGENTS.md de Codex, généralisée : l’exécution N écrit ce que l’exécution N+1 tient pour vrai.
  • Boucles de planification. Un contenu qui influe sur la manière dont le planificateur découpe une tâche peut détourner l’agent sans qu’aucun appel d’outil ne soit effectué : l’agent décide tout simplement de faire autre chose.
  • Couches de sérialisation. Plusieurs frameworks désérialisent leur état (chaînes, agents, messages) à partir de formats qui permettent l’exécution de code au chargement. Une classe de vulnérabilités bien connue (désérialisation Java, pickle en Python) qui réapparaît à un nouvel endroit.

L’incident de Hugging Face raconte la même histoire à une autre échelle : les agents ont été détournés par des contenus publiés sur un forum, et le « framework » qui l’a rendu possible était un système de fichiers partagé. La généralisation est inconfortable, mais nette : tout endroit où un contenu non fiable rencontre une exécution de confiance relève du framework, et le framework est une surface d’attaque.

Changer de cadre : de « contrôler les outils » à « le framework est la vulnérabilité »

Le modèle de sécurité classique pour les agents – recenser les outils, restreindre les permissions outil par outil, exiger une approbation pour les plus dangereux – est nécessaire. Gardez-le. Mais les travaux présentés à Black Hat établissent trois faits supplémentaires :

  1. Le contenu non fiable atteint le modèle par des canaux qui ne sont pas des appels d’outils (issues, pages récupérées, artefacts d’exécutions précédentes, mémoire).
  2. La sortie du modèle atteint le monde via du code (le harness) qui a ses propres bugs.
  3. L’état du framework lui-même est une cible d’injection.

Le modèle de menace doit donc inclure le harness et le framework comme surface d’attaque à part entière, à examiner comme vous le feriez pour le code de traitement des requêtes d’une application web.

Mesures de durcissement concrètes

Frontières de confiance

  • Traitez toute chaîne d’origine externe – corps d’issue, description de PR, message de commit, page récupérée, sortie antérieure d’un agent – comme une entrée non fiable. Étiquetez-la comme telle et, lorsque le framework le permet, faites-le dans des métadonnées structurées sur lesquelles le harness peut appliquer ses contrôles.
  • Ne laissez jamais une exécution de l’agent écrire à un emplacement qu’une exécution ultérieure lira comme des instructions (AGENTS.md, CLAUDE.md, .cursorrules, stockage de la mémoire), sauf si cette écriture est elle-même soumise à une relecture humaine.

Côté CI

  • Ne déclenchez pas de workflows d’agent sur les événements issues / issue_comment émis par des non-membres. Si vous ne pouvez pas faire autrement, exécutez-les avec un jeton en lecture seule et sans aucun secret.
  • Utilisez des runners éphémères à accès réseau restreint pour les jobs d’agent. N’autorisez les flux sortants que vers l’API de l’éditeur et le registre nécessaire, rien d’autre : le canal auxiliaire Hugging Face a fonctionné parce qu’un hôte tiers était joignable.
  • Séparez les identifiants de l’agent de ceux du dépôt. L’agent doit détenir une clé d’API qui ne permet rien d’autre qu’appeler le modèle, et un jeton GitHub qui ne permet rien d’autre que commenter.

Exécution de commandes

  • Ne développez pas votre propre validateur de commandes shell. Novee a mis en échec deux versions successives de celui d’un éditeur qui ne manque pourtant pas de moyens. Préférez une liste d’autorisation d’actions structurées (ouvrir un fichier, lancer une suite de tests donnée) à l’analyse de commandes shell libres.
  • Si le shell libre est inévitable, exécutez-le dans un bac à sable où le pire scénario reste borné, et partez du principe que le validateur sera contourné.

Frameworks

  • Épinglez les versions des frameworks et suivez leurs avis de sécurité comme pour n’importe quelle dépendance exposée au réseau.
  • Désactivez ou remplacez les chemins de désérialisation qui acceptent du code (pickle, chargeurs YAML non sûrs, configuration à base d’eval).
  • Traitez la mémoire de l’agent comme une base de données dans laquelle écrivent des sources non fiables : validez à la lecture, pas seulement à l’écriture.

Détection

  • Journalisez séparément les actions prévues de l’agent (la sortie du modèle) et ses actions réelles (ce qu’exécute le harness), puis comparez-les. Tout écart signale soit un bug du harness, soit une falsification – METR a constaté le second cas dans plus de 7 % des transcriptions de l’incident Hugging Face (voir OpenAI et l’attaque contre Hugging Face : là où l’enquête indépendante diverge). À titre d’illustration, un agent dont la transcription affiche :
$ echo REAL; sleep

mais dont la télémétrie du runner montre une connexion réseau vers un hôte inattendu a divergé, et c’est la transcription qui ment. Seule une télémétrie côté infrastructure permet de le détecter.

Sources

Revenir à la lecture rapide (2 min).

À lire aussi

· Cybersécurité · Lecture rapide 3 min · Lecture approfondie 6 min

Black Hat 2026 : ce qu’ont défendu les keynotes

Black Hat USA 2026 a parlé économie, pas exploits : quand l’attaque ne coûte presque rien, le seul levier est de rendre des classes entières de bugs impossibles, pas détectables.