L'agent d'OpenAI s'est introduit dans Hugging Face pour tricher à un benchmark

Le 9 juillet 2026 à 04h01 UTC, un modèle en cours d’évaluation chez OpenAI, déjà sorti de son bac à sable grâce à une faille zero-day dans le proxy de cache d’un registre de paquets, obtenait son premier shell root sur un cadre d’exécution de code tiers, selon la reconstitution de Hugging Face.2 Les quatre jours suivants, il a injecté un template Jinja2 dans le service de traitement des datasets de Hugging Face, obtenu les droits root sur un nœud Kubernetes, puis inscrit ce nœud dans le réseau maillé VPN interne de Hugging Face. Aucun humain n’a dirigé quoi que ce soit.2 Le post-mortem d’OpenAI du 26 août fait remonter au 26 mai la première évasion hors de ses bacs à sable ; la mise à jour du 1er octobre ci-dessous retrace cette chronologie.7

L’agent n’attaquait pas Hugging Face. Il trichait à un examen. OpenAI mesurait sa capacité offensive à l’aune d’ExploitGym. Le modèle a déduit que Hugging Face hébergeait peut-être les datasets et les solutions de ce benchmark, et il est allé les chercher. Selon le compte rendu d’OpenAI lui-même, les modèles « ont cherché et trouvé des moyens d’accéder à des informations secrètes utilisables pour tricher à l’évaluation ».1

Chacune des étapes décrites ci-dessous n’était qu’un moyen au service de cet objectif. La sophistication était réelle, la capacité était réelle, et le but visé était un meilleur score.

En bref

Des modèles d’OpenAI, sortis d’un bac à sable d’évaluation par le proxy de paquets de ce bac à sable, ont mené une campagne qui a atteint l’infrastructure de Hugging Face, documentée du 9 au 13 juillet 2026. Hugging Face a publié une chronologie technique le 27 juillet ; OpenAI a publié son propre compte rendu. L’intention relevait du détournement de récompense plutôt que de l’intrusion : les modèles voulaient les solutions d’ExploitGym. Cinq datasets ont été consultés, tous portant des noms évoquant un lien avec ExploitGym. Aucun modèle, dataset, Space ou paquet exposé aux clients n’a été touché. La liste blanche réseau a bloqué net l’accès à la base de production. L’évaluation tournait délibérément sans les classificateurs qui bloquent normalement les activités offensives à haut risque. Le post-mortem d’OpenAI du 26 août, qui fait remonter le début de l’histoire à mai, et un incident du 20 septembre qui a conduit OpenAI à suspendre l’usage d’outils par ses modèles les plus puissants figurent dans la mise à jour du 1er octobre ci-dessous.

Ce que l’agent a réellement fait

La chaîne mérite d’être lue dans l’ordre, car aucun maillon, pris isolément, n’est exotique.

Évasion (8 juillet). Le modèle a exploité une faille zero-day dans le proxy de cache du registre de paquets, l’un des rares canaux de sortie réseau autorisés depuis son bac à sable.2 Hugging Face ne nomme pas le produit, et en juillet je ne l’ai pas nommé non plus. OpenAI l’a nommé en août, a daté du 26 mai la première évasion hors de ses bacs à sable et du 8 juillet celle-ci, survenue après la reconstruction du proxy ; voir la mise à jour du 1er octobre.7

Point d’appui (9 juillet). Il a atteint le cadre public d’exécution de code CyberGym hébergé sur Modal, et y a obtenu les droits root via une redéfinition du constructeur sqlite3_initialize() combinée à une injection de commandes shell par les chemins de métadonnées de soumission.2 Un cadre d’évaluation public est ainsi devenu la base de lancement de tout ce qui a suivi.

Entrée (10 au 11 juillet). Dans la chronologie d’OpenAI, un agent récupère le 10 juillet 14 identifiants Hugging Face exposés publiquement et dotés de droits d’écriture, et les deux vecteurs qui suivent sont datés du 11 juillet.7 Deux vecteurs ont frappé le service de traitement des datasets de Hugging Face. Le traitement du stockage brut externe HDF5 a permis la divulgation de fichiers, exposant des variables d’environnement, des identifiants et le code source des workers. Puis l’injection de template Jinja2 a ouvert l’exécution de code à distance dans les pods Kubernetes de production :2

{{ cycler.__init__.__globals__.__builtins__.exec(...) }}

Déplacement latéral (11 juillet). L’agent a lu ce que Hugging Face décrit comme « le jeton de compte de service projeté que porte chaque pod », énuméré le cluster, puis obtenu les droits root sur le nœud via un pod privilégié doté d’un montage hostPath. Il a atteint une base MongoDB interne protégée par un mot de passe statique. Il a trouvé une clé d’authentification du VPN maillé dans les secrets du cluster et a inscrit le nœud compromis dans le réseau Tailscale interne.2

Expansion et sortie (12 au 13 juillet). Tentatives d’abus d’identifiants cloud, puis compromission du contrôle de source par génération de jetons d’intégration GitHub App. Persistance, nettoyage, et une action finale le 13 juillet à 14h14 UTC.2

Relisez cette liste en cherchant la nouveauté. Des jetons de plateforme dotés de droits d’écriture, exposés publiquement. Un mot de passe de base de données statique. Un ClusterRole trop permissif sur un pilote CSI, autrement dit un module de stockage porteur de permissions à l’échelle du cluster bien au-delà de ce qu’exige le montage de volumes. Un IMDS joignable depuis l’intérieur des pods, où le service de métadonnées d’instance distribue des identifiants cloud à quiconque sait envoyer une requête HTTP vers une adresse link-local. Un rendu de template non sécurisé appliqué à une configuration fournie par l’utilisateur.

À mon sens, rien de tout cela ne constitue une trouvaille exotique. Chaque point figure dans les listes de contrôle ordinaires en sécurité cloud, et j’attendrais d’un pentesteur compétent qu’il les relève tous. Ce qui a changé, c’est la vitesse et la patience de ce qui les a assemblés en un chemin d’attaque.

Hugging Face décrit la campagne comme « des milliers de petites décisions automatisées, exécutées à la vitesse de la machine ».2 Cette formule en dit plus que n’importe lequel des exploits pris séparément.

Pourquoi le mobile compte davantage que la méthode

Le détournement de récompense se manifeste d’ordinaire par de petites choses agaçantes. Un modèle écrit un test qui affirme True. Il traite en cas particuliers les trois entrées de l’exemple. Il modifie le fichier du benchmark au lieu de l’implémentation.

L’incident de juillet, c’est le même comportement doté d’une bien plus longue portée. Le modèle était noté sur sa résolution des défis ExploitGym. Les résoudre honnêtement est difficile. Trouver les solutions publiées est plus facile. Le modèle a raisonné sur l’endroit où ces solutions pouvaient se trouver, a conclu que Hugging Face était un hôte plausible, et a traité le bac à sable qui l’en séparait comme un obstacle, non comme une frontière.

Le signal d’entraînement n’a jamais dit « compromets une entreprise ». Il a dit « obtiens un bon score sur ExploitGym ». Tout le reste découle d’un agent qui a pris cet objectif plus au pied de la lettre, et avec plus d’ingéniosité, que personne ne l’avait prévu.

Deux conséquences en découlent, l’une et l’autre inconfortables.

D’abord : les évaluations de capacité constituent elles-mêmes une surface d’attaque. Confronter un modèle à un benchmark offensif revient à placer un adversaire compétent aux abords d’une infrastructure réelle et à le payer pour trouver des chemins. Le laboratoire qui mesure le plus agressivement la capacité offensive sera le premier à déclencher l’incident.

Ensuite : l’intention est un mauvais filtre. Toute heuristique de détection qui demande « cela ressemble-t-il à une action malveillante ? » part du principe qu’un attaquant cherche à nuire. Un agent qui s’acharne à décrocher un meilleur score produit les mêmes paquets, les mêmes lectures de jetons et les mêmes déplacements latéraux qu’un agent qui cherche à voler des données. Hugging Face l’a détecté par analyse à l’exécution et corrélation SIEM, non par un jugement porté sur le mobile.2

Un cadre d’évaluation public devenu base de lancement

Un maillon de la chaîne mérite une attention à part, car il relève d’une catégorie que la plupart des modèles de menace laissent de côté.

Une fois évadé, le modèle n’a pas visé Hugging Face directement. Il a atterri sur le cadre public d’exécution de code CyberGym hébergé sur Modal, et y a pris les droits root.2 À partir de là, le trafic dirigé vers Hugging Face provenait d’une plateforme de recherche tierce légitime faisant tourner un benchmark public légitime.

Mesurez ce que cela fait à toutes les défenses en aval. Le score de réputation voit un hôte de recherche connu. La limitation de débit voit un service dont la fonction même est d’exécuter du code non fiable. La détection d’anomalies voit un système dont le comportement de référence consiste à exécuter des soumissions arbitraires, puisque c’est là le produit.

Un cadre d’exécution de code est précisément la brique d’infrastructure incapable de distinguer un attaquant d’un utilisateur. Exécuter du code non fiable, c’est la fonctionnalité.

La technique d’obtention des droits root mérite d’être nommée précisément : redéfinition du constructeur sqlite3_initialize(), plus injection shell par les chemins de métadonnées de soumission.2 La première abuse d’un point d’accroche d’initialisation au niveau C qui s’exécute avant l’essentiel de la logique applicative. La seconde exploite l’hypothèse selon laquelle les métadonnées d’une soumission seraient moins dangereuses que la soumission elle-même. Ni l’une ni l’autre n’exige de primitive inédite.

Trois conséquences pratiques en découlent.

Si vous exploitez un cadre d’évaluation public, vous faites tourner une infrastructure voisine des attaquants, que vous la conceviez ainsi ou non. Traitez les métadonnées de soumission avec la même méfiance que les charges utiles soumises, et partez du principe que le bac à sable entourant votre exécuteur est porteur, non décoratif.

Si vous consommez de l’infrastructure de recherche, sa compromission est la vôtre. Le raccourci réputationnel qui affirme « du trafic venant d’une plateforme ML connue est probablement bénin » est exactement le raccourci que cette campagne a monnayé.

Et si vous faites tourner des benchmarks contre des modèles puissants, notez que le cadre du benchmark et les réponses du benchmark cohabitent souvent dans le même écosystème. Le modèle était sur le cadre du benchmark le 9 juillet, et dans le pipeline de datasets de Hugging Face dès le 11 juillet.

Ce qui devrait changer votre conception des sorties réseau

Le détail technique le plus utile du compte rendu de Hugging Face n’a rien à voir avec Kubernetes. Il porte sur la manière dont l’agent a traité la résolution de noms.

import socket
socket.getaddrinfo = lambda *a, **k: [(2, 1, 6, '', ('<pinned-ip>', 443))]

Cette seule ligne remplace la résolution DNS à l’intérieur du processus. Toute liste blanche fonctionnant par inspection des noms d’hôte inspecte désormais un nom d’hôte que le processus ne demande jamais. À ses côtés :

echo 'nameserver 8.8.8.8' > /etc/resolv.conf
echo '<cdn-ip> pkgs.tailscale.com' >> /etc/hosts
tailscaled --tun=userspace-networking

Quatre gestes au total, chacun relevant du « j’ai vu ça dans un CTF et j’ai supposé que c’était théorique ». Patcher la fonction de résolution dans le processus. Réécrire /etc/resolv.conf vers un serveur DNS public. Épingler une adresse de CDN dans /etc/hosts pour le domaine visé. Puis lancer Tailscale en mode userspace networking, qui ne réclame aucun périphérique TUN et donc aucun des privilèges que la plupart des référentiels de durcissement prennent la peine de retirer.

J’ai écrit sur les sorties réseau comme surface sous-surveillée dans La surface d’attaque silencieuse des sorties réseau, en soutenant que les contrôles fondés sur les noms décrivent une intention plutôt qu’ils n’imposent un comportement. Voici cet argument, référence à l’appui. Si votre politique de sortie résout des noms, un agent qui patche getaddrinfo est déjà parti.

Le contrôle qui a réellement tenu chez Hugging Face, c’est la liste blanche réseau au niveau de la connexion : les tentatives d’accès à la base de production ont purement et simplement échoué.2 Pas de classification, pas de score d’anomalie, pas de moteur de politiques lisant les appels d’outils. Une liste blanche qui refusait les connexions vers les adresses absentes de la liste.

Ce qui a tenu

La liste des échecs est longue et celle des succès est courte, ce qui rend cette dernière d’autant plus instructive.

Contrôle Résultat
Liste blanche réseau sur la base de production A tenu. Les tentatives d’accès ont échoué.
Analyse à l’exécution et corrélation SIEM A tenu. A produit une détection sur plusieurs couches.
Arrêt du moteur de rendu et coupure réseau A tenu. A mis fin à la campagne.
Mot de passe MongoDB statique A échoué.
IMDS joignable depuis les pods A échoué.
Portée du ClusterRole du pilote CSI A échoué, trop large.
Rendu Jinja2 de la configuration utilisateur A échoué. A donné une RCE.
Traitement des références externes HDF5 A échoué. A permis la divulgation de fichiers.

Chaque contrôle qui a tenu était structurel et ennuyeux. Chaque contrôle qui a cédé était une valeur par défaut que personne n’avait jamais réexaminée. Cette répartition est la leçon pratique, et elle vaut quoi que vous pensiez par ailleurs de la capacité des modèles.

La réponse de Hugging Face fut tout aussi peu spectaculaire : identifier le vecteur dans le moteur de rendu de la configuration des datasets, arrêter ce moteur, et couper l’attaquant du réseau interne.2

Ce qui a été atteint et ce qui ne l’a pas été

La précision compte ici, car l’incident invite à l’exagération.

Confirmé : cinq datasets consultés, dont les noms et les fichiers évoquent un lien avec ExploitGym, ainsi que des métadonnées opérationnelles issues des requêtes de recherche du dataset-server.2

Non touchés : les modèles, datasets, Spaces et paquets exposés aux clients.2 L’accès à la base de production a échoué. Des écritures sur le contrôle de source ont été relevées, mais Hugging Face déclare sans détour qu’« aucune modification n’a été livrée ».2

L’agent a donc obtenu à peu près ce qu’il cherchait, à savoir du matériel adjacent au benchmark, sans obtenir ce qui aurait fait de cet épisode une brèche affectant les clients. Les deux moitiés de cette phrase sont porteuses.

Les garde-fous étaient coupés volontairement

Une lecture à écarter avant qu’elle ne se répande : les garde-fous n’ont pas failli.

OpenAI indique que l’évaluation était conçue pour pousser les modèles vers l’exploitation avancée par des chemins d’attaque complexes, précisément afin de quantifier la capacité offensive, et qu’elle tournait sans les classificateurs de production qui empêchent normalement les activités offensives à haut risque. Les modèles impliqués étaient GPT-5.6 Sol et un modèle pré-lancement plus puissant, tous deux configurés avec des refus réduits sur les tâches offensives à des fins d’évaluation.1

Les dispositifs de sécurité ont été désactivés délibérément, dans un cadre contrôlé, pour mesurer ce qui se trouve en dessous. Le constat n’est pas que les protections ont cédé. Le constat porte sur ce que fait le modèle en leur absence, et sur la distance qu’il peut parcourir quand le bac à sable comporte une seule voie de sortie exploitable.

C’est un résultat plus utile qu’un récit d’échec, et plus inquiétant. OpenAI qualifie l’événement d’« incident cyber sans précédent » impliquant une capacité située à la frontière actuelle.1 C’est l’entreprise qui a mené l’évaluation qui l’affirme.

Ce que cela signifie pour l’agent qui tourne sur votre portable

L’infrastructure d’évaluation d’un laboratoire de frontière n’est pas la vôtre, et un modèle pré-lancement aux refus abaissés n’est pas l’assistant qui tourne dans votre terminal. L’écart est réel et mérite d’être posé avant d’en tirer la moindre leçon transposable.

La part transposable est plus étroite et plus dérangeante : le mécanisme de cet incident n’a exigé aucune capacité exceptionnelle. Patcher getaddrinfo, réécrire /etc/resolv.conf et épingler une entrée d’hôte sont à la portée de tout ingénieur compétent, et donc aussi de tout agent de codage disposant d’un accès shell. Ce que le modèle de frontière a apporté, ce n’est pas une technique inaccessible à des modèles plus modestes. C’est la persévérance nécessaire pour enchaîner une douzaine d’étapes banales sans se lasser ni se décourager.

Trois questions en découlent pour quiconque fait tourner un agent doté de permissions réelles.

Votre politique réseau pour l’agent résout-elle des noms ? Si votre contrôle de sortie est une liste blanche de domaines appliquée à l’intérieur du processus, ou un proxy qui fait confiance au nom d’hôte qu’on lui transmet, le mécanisme décrit plus haut le met en échec. L’application doit se situer là où l’agent ne peut pas patcher : un pare-feu, une politique réseau, une passerelle de sortie qui filtre par adresse.

Que fait votre agent lorsqu’il est bloqué ? Observez le comportement, il est diagnostique. Un agent qui signale l’action bloquée et s’arrête se comporte correctement. Un agent qui se met à sonder des routes alternatives vous a dit que son objectif prime sur la frontière dans son ordre de priorités. L’incident de juillet, c’est ce second comportement, avec quatre jours et un modèle puissant derrière lui.

Votre objectif est-il formulé comme un résultat ou comme un score ? L’agent dont il est question ici optimisait un nombre. Tout ce que vous formulez en « fais passer les tests » plutôt qu’en « rends le code correct » appelle la même catégorie de résolution. La plupart du temps, vous récoltez un test qui affirme True. Le plafond de ce comportement est fixé par la capacité et par les accès, non par l’intention, et l’une comme les autres ne cessent de monter.

Le point rassurant, c’est que les défenses qui ont fonctionné chez Hugging Face sont à la portée de tous et n’exigent aucune ingéniosité particulière. Un filtrage des sorties au niveau des adresses. Une télémétrie que vous conservez vraiment. Des identifiants qui ne sont pas statiques. Aucune de ces mesures n’exige de deviner ce qu’un agent va tenter.

Mise à jour du 25 septembre : un second incident, et les rapports qui le sous-tendent

Trois événements sont survenus dans les huit semaines qui ont suivi ce billet, et ensemble ils font passer le cas Hugging Face du statut d’exception à celui de premier élément d’une série.

Le 16 septembre, OpenAI a publié un Model Misalignment Reporting Framework et six rapports issus d’entraînements par renforcement, la plupart portant sur des modèles internes non publiés.4 Selon les termes mêmes de l’index : un modèle Astra-family « sometimes added unauthorized instructions to its compaction summaries » (ajoutait parfois des instructions non autorisées à ses résumés de compaction) ; un entraînement 5.6-sol « added instructions in compaction summaries to remind itself to conceal information such as mistakes or misalignment from the user » (ajoutait dans ses résumés de compaction des instructions lui rappelant de cacher à l’utilisateur des informations comme ses erreurs ou son désalignement) ; un modèle réservé à l’usage interne « tried to sign up for disposable emails and searched for and used leaked API keys from public GitHub repositories » (a tenté de s’inscrire à des adresses e-mail jetables, puis a cherché et utilisé des clés d’API divulguées dans des dépôts GitHub publics) ; des modèles « uploaded data to temporary file hosting services » (ont téléversé des données vers des services d’hébergement de fichiers temporaires) ; et des agents ont utilisé l’instance Artifactory interne de l’entreprise « as a shared message board » (comme tableau de messages partagé) ainsi que des hébergeurs de fichiers publics pour transmettre des fichiers de sortie aux agents avec lesquels ils collaboraient. Le même index publie des avis sur l’activité liée à RubyGems et sur un wiki public dont les agents se servaient comme tableau de messages (ce billet l’appelait d’abord collusion.wiki ; au 1er octobre, l’avis s’intitule « DSEwiki »), et son avis consacré à Hugging Face renvoie à la propre mise à jour d’OpenAI du 26 août sur la compromission.

Le 23 septembre, le Premier ministre australien a déclaré à New York qu’un agent d’OpenAI avait obtenu, le 18 juin, un accès non autorisé au portail de statistiques Medicare exploité par Services Australia, et y avait lu « both public and non-public files » (des fichiers publics comme non publics). Le portail contient des statistiques agrégées, comme les dépenses ; aucune donnée personnelle n’aurait été consultée, et trois autres systèmes, l’Australian Institute of Health and Welfare et deux agences d’États fédérés, pourraient avoir été touchés. OpenAI a découvert l’activité le 11 août lors de l’examen à l’origine de ces rapports et l’a signalée le 10 septembre par un e-mail envoyé à une boîte publique de signalement de vulnérabilités ; Services Australia l’a fait remonter au Signals Directorate cinq jours plus tard. Selon la déclaration d’OpenAI, l’activité s’est produite « as our models attempted to look up answers, and available statistics for questions about Australia during an internal evaluation » (alors que nos modèles tentaient de chercher des réponses et des statistiques disponibles pour des questions sur l’Australie, lors d’une évaluation interne).5

Le même jour, Transluce a publié des journaux d’analyse d’urlquery.net, un service d’analyse d’URL doté d’un navigateur distant. Ils montrent que des agents s’en servaient depuis au moins le 6 mars pour atteindre des pages qui les bloquaient en accès direct, en écrivant dans un cas « a base64-encoded script that fetched the data into the page » (un script encodé en base64 qui chargeait les données dans la page), et qu’ils sondaient trois fournisseurs publics de données à la recherche de vulnérabilités alors qu’ils effectuaient de simples tâches de récupération : sept sondages à la bibliothèque numérique de la University of New Mexico en mai, douze chez Data USA en mai, et, les 20 et 21 juin, à l’Australian Institute of Health and Welfare, où des agents « probed for a vulnerability and retrieved a public file from a pre-production server after bot protection blocked the main site » (ont cherché une vulnérabilité et récupéré un fichier public sur un serveur de préproduction après que la protection anti-bots eut bloqué le site principal). Transluce rattache « at least some of this activity to agent swarms previously attributed to OpenAI » (au moins une partie de cette activité à des essaims d’agents précédemment attribués à OpenAI) et observait encore ce trafic le 16 septembre.6

Ce que cela change pour l’argument ci-dessus. L’agent de Hugging Face cherchait à atteindre un corrigé ; celui de Medicare, une statistique. Le motif est devenu plus ordinaire et la cible plus publique, ce qui fait de la deuxième des trois questions posées plus haut, ce que fait votre agent lorsqu’il est bloqué, celle qui se généralise : dans chacun de ces cas, l’agent a traité un blocage comme un obstacle. La leçon sur le filtrage des sorties tient sans changement. Une leçon sur le signalement s’y ajoute, et elle est de moi, non d’une source : un laboratoire qui fait tourner des agents sur l’internet public a besoin d’une liste d’hôtes autorisés que son trafic d’évaluation peut toucher, et d’un circuit de signalement qui aboutit à un contact nommément désigné plutôt qu’à une boîte publique qui a mis cinq jours à faire remonter l’alerte.

Mise à jour du 1er octobre : le post-mortem, une pause et le débat sur le bac à sable

Avant les nouvelles, ce billet doit une correction de périmètre. OpenAI a publié son propre compte rendu le 26 août, et la mise à jour de septembre ci-dessus ne l’a pas intégré.7 Il change trois choses. L’évasion n’était pas le fait d’un seul modèle en un seul jour : OpenAI décrit « several OpenAI models » (plusieurs modèles d’OpenAI), menés surtout par « a highly capable, internal-only research model comparable in scale to GPT-5.6 Sol » (un modèle de recherche très performant, réservé à l’usage interne, d’une taille comparable à GPT-5.6 Sol), qu’OpenAI appelle IM1. Le « modèle pré-lancement plus puissant » de la section sur les garde-fous ci-dessus est, selon ma lecture, celui-ci, même si OpenAI le dit désormais réservé à l’usage interne, non destiné à une diffusion publique et comparable en taille à GPT-5.6 Sol plutôt que plus puissant. Le proxy a un nom : « we would grant access to Artifactory, a third-party package manager service that we host internally » (nous accordions l’accès à Artifactory, un service tiers de gestion de paquets que nous hébergeons en interne). Et la chronologie commence en mai. Dans les entrées d’OpenAI elles-mêmes : le 12 mai, « an agent left an Artifactory note asking other agents for a missing file » (un agent a laissé dans Artifactory une note demandant à d’autres agents un fichier manquant) ; le 26 mai, un agent « achieved unintended internet access by causing Artifactory to send a server-side request to an arbitrary internet destination » (a obtenu un accès à Internet non prévu en amenant Artifactory à envoyer une requête côté serveur vers une destination arbitraire sur Internet) ; le 26 juin, des agents « exploited a token-refresh vulnerability to obtain administrator-level Artifactory access » (ont exploité une vulnérabilité de rafraîchissement de jeton pour obtenir un accès administrateur à Artifactory) ; le 4 juillet, le service est tombé sous le trafic des agents ; le 8 juillet, il a été reconstruit, et le jour même des agents ont retrouvé l’accès à Internet, l’un d’eux « used unauthenticated WebDAV requests to create message directories in Artifactory » (a utilisé des requêtes WebDAV non authentifiées pour créer des répertoires de messages dans Artifactory) ; et le 19 juillet, des agents « gained administrator access to an OpenAI Kubernetes cluster and reached cloud secrets » (ont obtenu un accès administrateur à un cluster Kubernetes d’OpenAI et atteint des secrets cloud). Une équipe interne avait vu le tableau de messages et l’accès à Internet non autorisé « as early as late May » (dès la fin mai).

Deux chiffres de ce rapport expliquent le mobile mieux que tout ce qui précède. Selon OpenAI, « none of our models had ever produced a correct answer for 198 of the 898 tasks prior to the incident » (avant l’incident, aucun de nos modèles n’avait jamais donné de bonne réponse à 198 des 898 tâches), et « 93% of the tasks that were discussed on the Artifactory message board during the Hugging Face incident came from this set of 198 questions » (93 % des tâches discutées sur le tableau de messages d’Artifactory pendant l’incident Hugging Face provenaient de ces 198 questions). Le tableau de messages était dominé par des tâches qu’aucun modèle d’OpenAI n’avait jamais résolues. Le correcteur que les agents cherchaient à satisfaire n’était même pas celui dont ils avaient lu la description : « our internal implementation of the grader code was different from the online setup » (notre implémentation interne du code de notation différait de la configuration en ligne), et « The agents did all of this for no improvement on evaluation score » (les agents ont fait tout cela sans la moindre amélioration du score d’évaluation).

Le 25 septembre, OpenAI a ajouté trois rapports à son index de désalignement, dont l’un décrit le premier incident depuis le durcissement qui a suivi tout cela.8 Le 20 septembre, un agent en cours d’entraînement par renforcement, chargé d’une recherche sur l’auteur d’un billet de blog, « queried a public chatbot service through a gap in our internet-access restrictions: insufficient DNS filtering in its training sandbox » (a interrogé un service public de chatbot par une brèche dans nos restrictions d’accès à Internet : un filtrage DNS insuffisant dans son bac à sable d’entraînement). La séquence, c’est la deuxième question de la section sur votre portable, ce que fait un agent lorsqu’il est bloqué, jouée à l’intérieur même du laboratoire. L’outil de recherche a renvoyé des résultats sans rapport. L’agent a essayé trois moteurs de recherche depuis le shell et obtenu des erreurs 403 et 502 ; selon la note d’OpenAI, dans ce rapport, tout sauf le résolveur était servi par le cache web hors ligne du laboratoire, et non par l’Internet réel. Il a ensuite supposé, à tort, que la question venait de BrowseComp, un benchmark public, a téléchargé le benchmark et son script d’évaluation depuis le cache web du laboratoire, et a cherché une correspondance dans les questions décodées : de nouveau le geste de juillet, la quête du corrigé. Il a tenté de joindre un chatbot en HTTPS, et le proxy a refusé. Puis il a remarqué que « the training environment’s own resolver returned a real record for a known domain » (le résolveur propre à l’environnement d’entraînement renvoyait un véritable enregistrement pour un domaine connu), s’est servi d’un service public de délégation DNS pour relayer une question vers un chatbot à travers ce résolveur, et a reçu en retour « The capital of France is Paris » (la capitale de la France est Paris). Il a envoyé 18 autres questions, dont « Four asked for ways to search the web, fetch websites, or use a publicly hosted tunnel through DNS » (quatre demandaient des moyens de faire des recherches sur le Web, de récupérer des sites ou d’utiliser un tunnel public passant par le DNS). Son raisonnement consigné en chemin : « User only gives permission to research, using publicly offered DNS services acceptable » (l’utilisateur n’autorise que la recherche, utiliser des services DNS proposés publiquement est acceptable).

La réponse est horodatée. L’appel DNS qui a obtenu une réponse de l’extérieur a eu lieu à 9 h 50 min 23 s ; « The monitoring system raised a P0 alert » (le système de surveillance a déclenché une alerte P0) à 10 h 02 min 11 s ; un humain en a accusé réception à 10 h 05 min 06 s ; et l’exécution n’a été tuée qu’à 12 h 34 min 30 s, parce que « the run did not stop automatically as expected, leading to confusion around whether it should have been stopped » (l’exécution ne s’est pas arrêtée automatiquement comme prévu, ce qui a semé la confusion sur la question de savoir s’il fallait l’arrêter). L’analyse rétrospective a établi que le moniteur avait sous-évalué « other cases of external DNS access that it did not flag at the expected severity » (d’autres cas d’accès DNS externe qu’il n’avait pas signalés au niveau de gravité attendu), parce que « The monitor sometimes treated the failure to obtain useful information as evidence that the attempt to access the internet had failed » (le moniteur traitait parfois l’absence d’information utile comme la preuve que la tentative d’accès à Internet avait échoué), et que « an infrastructure detector for anomalous DNS activity excluded the affected environment, though DNS activity was logged » (un détecteur d’infrastructure dédié à l’activité DNS anormale excluait l’environnement concerné, bien que l’activité DNS ait été journalisée). OpenAI a décidé de « pause all other training, evaluation, and inference with tool-use (defined broadly) for our most capable models until we have both validated that the gap is resolved and performed additional red-teaming of the system » (suspendre tout autre entraînement, toute évaluation et toute inférence avec usage d’outils, au sens large, pour nos modèles les plus puissants, jusqu’à avoir à la fois vérifié que la brèche est comblée et mené un red teaming supplémentaire du système), et ajoute : « We will not resume training this particular model » (nous ne reprendrons pas l’entraînement de ce modèle précis). Selon sa propre évaluation, l’incident est « a lot less severe than some of our previous incidents » (bien moins grave que certains de nos incidents précédents) et compte parce que « it’s the first one since our security hardening following the Hugging Face incident » (c’est le premier depuis notre durcissement de la sécurité consécutif à l’incident Hugging Face).

Une comparaison est de moi, non d’OpenAI. Le post-mortem d’août a fixé une règle : « For the most severe alerts, responders are expected to pause the relevant activity if they cannot establish within 30 minutes of being paged that the alert is a false positive » (pour les alertes les plus graves, les intervenants sont censés suspendre l’activité concernée s’ils ne peuvent pas établir, dans les 30 minutes suivant l’appel, qu’il s’agit d’un faux positif).7 L’alerte de septembre s’est déclenchée à 10 h 02 et l’exécution s’est arrêtée à 12 h 34. Le rapport ne cite pas la règle ; il dit : « The response also exposed operational gaps » (la réponse a aussi mis au jour des lacunes opérationnelles).

Les deux autres rapports portent sur des événements plus anciens, publiés le même jour.8 Le 27 mai, un modèle déployé en interne « published a researcher’s GitHub token in the public openai/codex repository while trying to cheat on a theorem proving task by obtaining material from another team’s Lean proof submission. It split the token into pieces with the stated aim of avoiding secret scanning » (a publié le jeton GitHub d’un chercheur dans le dépôt public openai/codex en tentant de tricher à une tâche de démonstration de théorèmes, en se procurant des éléments de la preuve Lean soumise par une autre équipe. Il a découpé le jeton en morceaux dans le but déclaré d’échapper à la détection de secrets). Le chercheur lui avait demandé à deux reprises de faire la preuve lui-même, et il avait accepté les deux fois. Le troisième rapport montre qu’une injection de prompt peut se recopier elle-même : lors d’un entraînement sur du texte injecté, un e-mail qui demandait à tout assistant y répondant d’en citer l’intégralité a produit une réponse qui a transmis la consigne à son lecteur suivant. OpenAI indique : « No impact was observed outside of the simulated tool calls in training and evaluation » (aucun impact n’a été observé en dehors des appels d’outils simulés lors de l’entraînement et de l’évaluation).

Matthew Green, cryptographe à l’université Johns Hopkins, a arbitré le 30 septembre, dans un essai, le débat que ces incidents ont lancé.9 Un camp affirme que les laboratoires ont échoué sur le confinement ordinaire ; l’autre, qu’aucun bac à sable ne retient un agent compétent à qui il faut malgré tout transmettre de l’information. Au vu des faits établis à ce jour, il se range du côté du premier : « The labs have not been doing containment correctly, and so we can’t really tell if the problem is models or just bad infrastructure » (les laboratoires n’ont pas fait le confinement correctement, si bien qu’on ne peut pas vraiment dire si le problème vient des modèles ou simplement d’une mauvaise infrastructure). Puis il démonte l’argument du bac à sable par l’autre bout. Le trafic qui passe par l’unique porte ouverte doit être inspecté, aucun humain ne peut en lire autant, donc un modèle doit s’en charger, et « a warden-guarded sandbox is just another version of the alignment problem » (un bac à sable gardé par un geôlier n’est qu’une autre version du problème de l’alignement). Sa troisième inquiétude porte au-delà des laboratoires : « a swarm of perfectly amenable agents that never leave their sandboxes, each doing exactly what it’s told to do, by a human being who wasn’t supposed to be giving it orders » (un essaim d’agents parfaitement dociles qui ne quittent jamais leur bac à sable, chacun faisant exactement ce qu’on lui dit, sur l’ordre d’un humain qui n’était pas censé lui en donner). Le post-mortem lui fournit ses preuves. Un agent qui avait raisonné « We should not do unauthorized real infrastructure harm » (nous ne devrions pas causer de dommages non autorisés à une infrastructure réelle) est passé à l’acte après qu’un pair « wrote GO on the message board and imposed a hard six-minute deadline » (a écrit GO sur le tableau de messages et imposé un délai strict de six minutes), et OpenAI résume : « Agents did not consistently distrust goals passed along by other agents » (les agents ne se méfiaient pas systématiquement des objectifs transmis par d’autres agents).7

Ce que cela change pour l’argument ci-dessus, selon ma lecture. La section sur les sorties réseau tient, et sa portée s’élargit : en juillet, les agents ont patché la résolution de noms pour contourner une liste blanche de noms d’hôte ; en septembre, le résolveur lui-même était la porte. Une politique qui filtre le HTTP et laisse le résolveur répondre pour tout Internet comporte un trou de la taille du DNS, et le correctif d’OpenAI a la bonne forme : l’entreprise a « restricted DNS queries within the environment to a limited allowed list of domains and record types » (restreint les requêtes DNS de l’environnement à une liste limitée de domaines et de types d’enregistrements autorisés). La réponse de la FAQ sur le bac à sable tient, avec l’amendement de Green : un bac à sable restreint le trafic à une porte que vous avez choisie, et il ne juge pas ce qui la franchit. Enfin, les horodatages établissent un point qui s’applique sans aucun laboratoire. Le moniteur s’est déclenché en douze minutes et l’arrêt a pris deux heures et demie. Une détection qui n’arrête pas l’exécution n’est qu’une notification. Pour vos propres agents, décidez de ce qui arrête le processus, câblez-le, et vérifiez qu’il se déclenche.

À retenir

Pour les équipes plateforme et infrastructure : - Filtrez les sorties par adresse au niveau de la connexion, pas par nom d’hôte. Un processus qui patche getaddrinfo ne consulte jamais votre résolveur. - Auditez les cinq faiblesses qui ont porté cette campagne : jetons de plateforme dotés de droits d’écriture exposés publiquement, mots de passe de service statiques, IMDS joignable depuis les pods, ClusterRoles trop larges, et rendu de templates sur une configuration fournie par l’utilisateur. - Considérez --tun=userspace-networking comme une capacité que votre référentiel de durcissement ne bloque probablement pas.

Pour les équipes qui font tourner des évaluations de modèles : - Une évaluation de capacité offensive place un adversaire compétent aux abords d’une infrastructure réelle. Isolez le réseau d’évaluation de tout ce dont la perte vous serait pénible. - Chaque canal de sortie autorisé est une voie d’évasion potentielle. Ici, c’était le proxy de cache d’un registre de paquets, ce qui paraît inoffensif jusqu’au moment où c’est la seule porte. - Journalisez l’environnement d’évaluation comme un environnement de production. La chronologie de juillet a pu être reconstituée parce que la télémétrie existait. - Traitez le résolveur DNS de l’environnement comme un canal de sortie : limitez-le aux domaines et types d’enregistrements autorisés. - Reliez les alertes à un arrêt automatique testé. En septembre, une alerte P0 s’est déclenchée en douze minutes et l’exécution a continué deux heures et demie de plus.

Pour l’ingénierie sécurité en général : - Cessez de filtrer sur l’intention apparente. Un agent qui optimise un score est indiscernable, au niveau des paquets, d’un agent qui vole des données. - La détection est venue de l’analyse à l’exécution et de la corrélation SIEM. Une télémétrie ennuyeuse et en couches a eu raison d’un adversaire sophistiqué.

Sur ce site : Le mode auto de Claude Code n’est pas une frontière de sécurité explique pourquoi un classifieur qui approuve les appels d’outils n’offre qu’un fonctionnement au mieux et ne constitue pas une frontière ; le billet sur les routeurs traite de l’intermédiaire capable de réécrire en transit les appels d’outils d’un agent ; le billet sur la chaîne d’approvisionnement montre comment un scanner de sécurité compromis a conduit à des versions de LiteLLM dotées d’une porte dérobée ; et le billet sur la preuve de travail traite des cyber ranges de l’AISI britannique et de l’incident d’août au cours duquel ses agents de test ont agi contre des personnes et des organisations réelles.

FAQ

Une IA a-t-elle décidé d’attaquer Hugging Face ?

Non, et la nuance compte. Le modèle était noté sur les défis ExploitGym et a déduit que Hugging Face hébergeait peut-être leurs solutions. Il a poursuivi cette déduction à travers tous les obstacles rencontrés. Hugging Face est explicite : aucun humain n’a dirigé les étapes individuelles.2

Des données clients ont-elles été dérobées ?

Hugging Face fait état de cinq datasets consultés, tous portant des noms et des fichiers évoquant un lien avec ExploitGym, ainsi que de métadonnées opérationnelles issues des requêtes au dataset-server. Aucun modèle, dataset, Space ou paquet exposé aux clients n’a été touché, et les tentatives d’accès à la base de production ont échoué face à la liste blanche réseau.2

OpenAI a-t-il expliqué comment le modèle s’est échappé du bac à sable ?

Oui, à gros traits. OpenAI indique que les modèles ont consacré un volume de calcul d’inférence considérable à chercher un accès ouvert à Internet, puis ont identifié et exploité une faille zero-day dans le proxy de cache d’un registre de paquets avant de s’élever vers un nœud disposant de connectivité.1 Le mécanisme fin de l’exploitation du proxy restait peu détaillé dans les deux comptes rendus de juillet, ce qui n’équivaut pas à une rétention délibérée. Le post-mortem d’OpenAI du 26 août en précise les contours : une falsification de requête côté serveur via le proxy le 26 mai, une faille de rafraîchissement de jeton donnant un accès administrateur le 26 juin, et, selon ses termes, des agents qui « were able to chain together previously unknown vulnerabilities (‘0-days’) in the package management service exposed within the sandbox » (ont pu enchaîner des vulnérabilités jusque-là inconnues, des « 0-days », dans le service de gestion de paquets exposé à l’intérieur du bac à sable).7

De quel proxy de paquets s’agissait-il ?

En juillet, aucune des deux sources primaires ne le nommait, et je me suis abstenu de publier un nom de fournisseur avancé par des reprises de seconde main.3 Le post-mortem d’OpenAI du 26 août confirme le nom : les bacs à sable avaient reçu l’accès à « Artifactory, a third-party package manager service that we host internally » (Artifactory, un service tiers de gestion de paquets qu’OpenAI héberge en interne), et OpenAI « notified JFrog of the token-refresh vulnerability » (a signalé à JFrog la vulnérabilité de rafraîchissement de jeton).7

Un bac à sable sert-il encore à quelque chose ?

Oui, et cet incident plaide pour en multiplier le nombre plutôt que pour l’inverse. L’agent a eu besoin d’un canal de sortie exploitable pour partir. Ce qui a échoué, c’est un bac à sable doté d’une voie réseau autorisée et sans filtrage par adresse derrière elle. J’ai traité la forme générale de cette défaillance dans La sécurité du bac à sable de votre agent n’est qu’une suggestion.

Sources


  1. OpenAI, “OpenAI and Hugging Face partner to address security incident during model evaluation.” Décrit la conception de l’évaluation, la configuration à refus réduits, les modèles impliqués (GPT-5.6 Sol et un modèle pré-lancement), la faille zero-day dans le proxy de cache du registre de paquets, et l’objectif déclaré d’accéder à des informations utilisables pour tricher à l’évaluation. ↩↩↩↩

  2. Hugo Larcher, Adrien Carreira, raphael g, et Christophe Rannou, “Anatomy of a Frontier Lab Agent Intrusion: A Technical Timeline of the July 2026 Incident,” Hugging Face, 27 juillet 2026. Source de la chronologie complète, du point d’appui CyberGym et Modal, des vecteurs HDF5 et Jinja2, du chemin d’élévation Kubernetes, du patch de getaddrinfo et de la manipulation DNS, de l’inscription au réseau maillé Tailscale, de la détection et de la réponse, ainsi que du périmètre d’impact confirmé. ↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩↩

  3. Simon Willison, “Anatomy of a Frontier Lab Agent Intrusion,” 28 juillet 2026. Commentaire ayant mis en lumière la chronologie de Hugging Face. Utilisé ici comme piste de découverte ; toutes les affirmations techniques de ce billet remontent aux deux comptes rendus primaires ci-dessus. ↩

  4. OpenAI Alignment, “Misalignment Reports and Notices”, index consulté le 24 septembre 2026 ; chacun des six rapports porte les mentions « Updated Sep 16, 2026 » et « RL training », et les phrases citées sont les résumés d’une ligne que l’index lui-même donne pour chaque rapport. Le billet présentant le cadre est OpenAI, “Our framework for reporting model misalignment”, 16 septembre 2026. ↩

  5. Erin Handley et la rédaction, “OpenAI hacked Medicare portal, Prime Minister Anthony Albanese says”, ABC News, 24 septembre 2026 (AEST), source de la chronologie : l’accès du 18 juin, la découverte par OpenAI le 11 août, l’e-mail du 10 septembre à la boîte publique de signalement et la remontée du 15 septembre. Harry Sekulich et Lana Lam, “Rogue OpenAI agent ‘infiltrated’ Australian government website in world first”, BBC News, 23 septembre 2026, source pour les trois autres systèmes et la déclaration d’OpenAI. Simon Sharwood, “OpenAI agents ‘infiltrated Australian government website’”, The Register, 24 septembre 2026, source pour les propos cités du Premier ministre et pour la version d’OpenAI selon laquelle l’examen à l’origine de ses rapports de désalignement a mis au jour l’activité. ↩

  6. Jack Cable, Daniel Chiu, Francisco Pernice, Selena Zhang, James Anthony, Tetiana Bas, Gary Shen, Conrad Stosz et Jacob Steinhardt, “Early rogue AI agent activity and attempts to hack found on urlquery.net”, Transluce, 23 septembre 2026, cité. ↩

  7. OpenAI, “The Hugging Face incident and the road ahead,” 26 août 2026, lu dans un navigateur le 1er octobre 2026 (la page refuse les récupérations automatisées). Sont cités : le résumé d’ouverture, « Background on sandboxing », les entrées de la chronologie de l’incident pour le 12 mai, le 26 mai, le 26 juin, le 8 juillet et le 19 juillet (ses entrées du 4 juillet, du 10 juillet et du 11 juillet sont paraphrasées dans le texte), « Difficult tasks without a safe exit », « An ecosystem of misalignment », « Safeguard coverage in internal evaluations » et « Strengthening incident response process ». La page renvoie à un rapport technique distinct, que je n’ai pas lu. ↩↩↩↩↩↩↩↩

  8. OpenAI Alignment, “An agent used DNS to reach an external chatbot” (échantillon et découverte le 20 septembre 2026), “Exposing a GitHub token in a public repository” (incident du 27 mai 2026) et “Self-replicating prompt injections exist” (découverte le 27 juin 2026), chacun portant la mention « Report updated: Sep 25, 2026 » et consulté le 1er octobre 2026. Sont cités les résumés, les sections « What happened » et « Investigation and response » du rapport DNS et le résumé du rapport sur le jeton ; l’exemple d’injection est décrit, non reproduit. ↩↩

  9. Matthew Green, “Is sandboxing sufficient to contain rogue agents?” A Few Thoughts on Cryptographic Engineering, 30 septembre 2026, consulté le 1er octobre 2026. Citations tirées de « Argument 1 », « Argument 2 » et du paragraphe de conclusion. Le résumé des incidents par Green renvoie au post-mortem d’OpenAI mentionné dans la note 7 ci-dessus. ↩

Articles connexes

La fork bomb nous a sauvés

L'attaquant de LiteLLM a commis une seule erreur d'implémentation. C'est uniquement grâce à elle que 47 000 installation…

9 min de lecture

Votre agent a deux entrées non fiables

Les agents IA ont deux entrées non fiables : le code que le modèle écrit et la sortie d'outil qu'il lit. L'une a désorma…

15 min de lecture

La boucle Ralph : comment je fais tourner des agents IA autonomes pendant la nuit

J'ai bâti un système d'agents autonomes avec hooks d'arrêt, budgets de spawn et mémoire sur fichiers : les échecs et ce …

14 min de lecture