← Retour à tous les articles
Publié le · par Renaud Deraison

Quarante mille dollars par évasion

Le 6 octobre, à Pwn2Own Ireland, Ikotas Labs a sorti OpenAI Codex de son sandbox grâce à un seul bug d'injection d'arguments et a remporté 40 000 $. Les agents de code sont désormais une catégorie permanente de Pwn2Own : à Berlin en mai, Codex est tombé trois fois et trois équipes ont lancé des exploits contre Claude Code. Le règlement dit ce que signifie une victoire : l'agent ouvre le dépôt, la page web ou le fichier du concurrent avec son sandbox activé, et du code s'exécute en dehors. Dans Bromure Agentic Coding, en dehors du sandbox de l'agent, on est encore dans une VM Linux qui ne détient que des clés de substitution, avec ses sorties, ses dialogues de push et sa trace sur le Mac.

Pwn2Own paie 40 000 $ pour du code qui s'exécute en dehors du sandbox d'un agent de code. Sur un portable, en dehors du sandbox, il y a votre compte, vos clés et vos dépôts.

Le mardi 6 octobre à 18 h, à Cork, Ikotas Labs est monté sur scène à Pwn2Own Ireland 2026 avec OpenAI Codex pour cible. Dans les résultats de la Zero Day Initiative, l'entrée tient en une ligne : Ikotas « used a single argument injection bug to exploit OpenAI Codex. They win $40,000 and 4 more Master of Pwn points. » BleepingComputer et Infosecurity Magazine l'ont rapporté le lendemain matin parmi les 32 zero-days de la première journée.

ZDI ne publiera pas le bug avant 90 jours, le délai que Pwn2Own laisse aux éditeurs pour livrer un correctif. Le règlement du concours précise ce que l'exploit devait accomplir.

Ce que signifie une victoire

Les agents de code ont leur propre catégorie à Pwn2Own. Le règlement d'Ireland 2026 liste deux cibles, Anthropic Claude Code et OpenAI Codex, à 40 000 $ chacune, toutes deux sous Windows 11. Le cadre est strict :

  • Les fonctions de sandbox et d'isolation sont activées dans leur configuration par défaut, et aucun mode d'exécution non sûr (par exemple --dangerously-skip-permissions ou un équivalent) n'est actif.
  • La tentative « doit interagir avec une ressource contrôlée par le concurrent (par exemple une page web, un dépôt, un fichier multimédia) », et l'attaque « doit correspondre à un usage courant d'un agent de code ».
  • Elle doit obtenir une exécution de code arbitraire au-delà des « limites de sandbox et de permissions prévues » de l'agent, ou récupérer des informations sensibles « normalement inaccessibles depuis le sandbox de l'application ».

Le règlement prévoit trois points de départ. Soit l'agent tourne déjà dans un dossier de confiance et l'attaque se déroule au sein d'une seule session. Soit l'agent est lancé dans le dépôt du concurrent avant que quiconque lui ait accordé sa confiance. Soit une application de bureau ouvre le projet du concurrent. Ce sont les trois gestes qu'un développeur fait toute la journée : travailler, cloner quelque chose de nouveau, ouvrir quelque chose de nouveau.

Le règlement écarte aussi une liste de choses qui ne comptent pas : convaincre le modèle de le faire, les identifiants configurés dans l'environnement, les modes non sûrs, les serveurs MCP tiers. La prime ne paie qu'une chose : casser la frontière propre à l'agent.

Cinq mois, deux concours

Ireland est le deuxième Pwn2Own où figurent des agents de code. À Berlin en mai, Compass Security a exploité Codex dès le premier jour avec « a single CWE-150 bug », pour 40 000 $. Doyensec l'a exploité le même jour avec un bug que l'éditeur connaissait déjà, et le troisième jour Satoki Tsuji, d'Ikotas Labs, l'a exploité de nouveau via une vulnérabilité de contrôle externe, en lançant des calculatrices sur la cible. Security Affairs résumait ainsi les trois victoires contre Codex : « Each exploit used a different technique, meaning the attack surface is not a single narrow flaw but something broader. »

Claude Code a essuyé trois exploits à Berlin, signés Viettel Cyber Security, Compass Security et Out of Bounds. Les trois étaient des collisions : les bugs ont fonctionné sur scène, et Anthropic les connaissait déjà. Une collision rapporte moins parce que les chercheurs n'étaient pas les premiers, mais l'exploit a tout de même fonctionné contre la version installée pour le concours.

Puis est venu Ireland, cinq mois plus tard, et Codex est de nouveau tombé sur un seul bug.

ZDI n'a pas encore décrit le bug d'Ireland, mais l'injection d'arguments est une classe bien connue chez les agents de code. La couche de permissions d'un agent approuve une commande d'après son nom : git, rg, find sont en lecture seule et s'exécutent sans demander. L'attaquant fournit les arguments, via un nom de fichier, un nom de branche ou une valeur de configuration dans le dépôt, et l'outil « en lecture seule » reçoit une option qui exécute un programme. --upload-pack pour Git, --pre pour ripgrep et -exec pour find prennent tous une commande. En juillet, Pillar Security a signalé que la liste de commandes sûres de Codex faisait confiance à git show sur son seul nom alors que l'appel qu'il effectuait n'était pas en lecture seule.

Chacun de ces exploits déjoue une vérification qui vit à l'intérieur de l'agent, écrite par l'éditeur de l'agent et livrée avec ses mises à jour. Les éditeurs corrigent chacun d'eux, et le concours trouve le suivant, parce qu'une couche de permissions qui analyse des commandes shell est une cible large, et qu'une prime de 40 000 $ garde les bonnes équipes à l'affût.

Ce que l'évasion rapporte sur un portable

Le sponsor de Pwn2Own décide quelles « informations sensibles » l'exploit doit récupérer, et les juges le vérifient sur une machine de test propre. Sur le portable d'un développeur, personne n'a besoin de choisir un drapeau. En dehors du sandbox de l'agent, il y a votre compte utilisateur, et votre compte contient :

  • ~/.ssh/id_ed25519 et chaque hôte de known_hosts
  • ~/.aws/credentials, ~/.config/gcloud, ~/.kube/config
  • un jeton gh avec les droits de push, et des fichiers .env dans chaque checkout
  • le jeton OAuth de l'agent lui-même et son historique de sessions
  • tous les autres dépôts du disque, et les profils de navigateur à côté

Le concours exclut aussi des chemins que les vrais attaquants empruntent tous les jours. Une injection de prompt qui convainc l'agent d'exécuter une commande ne compte pas. Un développeur qui travaille en mode --yolo pour faire taire les demandes non plus. Dans la vraie vie, tous ces chemins mènent au même endroit qu'une évasion du sandbox : un processus qui tourne sous votre identité.

Sur un portable : une seule frontière, celle de l'agentPoints d'entréeDépôt, page ou fichier piégé+ un bug de sandbox (Pwn2Own)Injection de prompthors règlement du concoursMode non sûr ou « yolo »hors règlement du concourssandbox de l'agentVotre compte sur le portable~/.ssh/id_ed25519~/.aws/credentials ~/.kube/configjeton gh avec droits de push.env dans chaque checkoutjeton OAuth, historique agentautres dépôts, profils webRéseau : tout hôte,tout port, sans traceTout ce dont l'exploit a besoin est déjà là, la sortie aussi.
Sur un portable, le sandbox de l'agent est la seule ligne de défense. Une évasion façon Pwn2Own, une injection de prompt ou un mode non sûr aboutissent tous au même endroit : un processus avec le compte, les clés et le réseau du développeur.

La même évasion dans une machine Bromure

Dans Bromure Agentic Coding, Codex et Claude Code tournent dans une VM Linux sur votre Mac, une VM par machine. Le sandbox propre à l'agent est toujours là et fait toujours son travail. En dessous se trouve une seconde frontière que l'éditeur de l'agent n'a pas écrite et que le dépôt ne peut pas configurer : le Virtualization.framework d'Apple, avec l'hôte de l'autre côté.

Rejouez l'exploit d'Ikotas Labs dans une machine. L'agent ouvre le dépôt du concurrent, l'argument atteint une commande qui n'aurait pas dû l'accepter, et du code s'exécute en dehors du sandbox de Codex. Il tourne sous l'utilisateur de la VM. À partir de là, il cherche chaque élément de la liste du portable et trouve la version qu'en possède la VM.

Les fichiers sont ceux de la machine

La VM a son propre disque système, un clone copy-on-write d'une image Ubuntu signée, et son propre répertoire personnel. Le dossier personnel de votre Mac, votre trousseau, vos profils de navigateur et vos autres projets n'y sont pas. Les seuls dossiers du Mac qu'elle voit sont ceux que vous avez partagés avec cette machine dans son volet Folders, et une machine destinée à du code non fiable n'en a besoin d'aucun : clonez le dépôt dans le répertoire personnel de la VM.

Les clés sont des substituts

Aucun fichier, aucune variable d'environnement, aucun processus de la VM ne contient une vraie clé d'API, un jeton OAuth, un secret AWS ou une clé privée SSH. La VM détient des faux qui ont la bonne forme, comme ANTHROPIC_API_KEY=sk-ant-api03-brm-… ou un jeton ghp_ que GitHub refuserait. Le proxy sur le Mac substitue la vraie valeur une fois que la requête a quitté la VM, et seulement pour l'hôte auquel l'identifiant appartient.

~/.ssh ne contient aucune clé privée à copier. SSH_AUTH_SOCK est un pont via vsock vers un ssh-agent sur le Mac, qui signe à la demande et ne remet jamais la clé. Activez Ask before use pour une clé, et chaque signature ouvre un dialogue sur le Mac.

Les substituts servent aussi de pièges. Quand l'exploit emballe ce qu'il a trouvé et l'envoie chez lui, le proxy voit un faux jeton partir vers un hôte pour lequel il n'a pas été émis. Il répond HTTP 451, ne transmet rien, met la VM en pause et ouvre This environment may have been compromised sur le Mac, avec le jeton, l'hôte auquel il appartient et l'hôte vers lequel il a été envoyé.

La sortie passe par le Mac

Chaque connexion ouverte par la VM traverse le switch virtuel et le proxy sur l'hôte, quels que soient le port ou le protocole. Le volet Guardrails de la machine comporte un pare-feu de sortie : des règles par hôte, plage d'adresses IP, protocole et port, et un réglage Unmatched traffic sur Allow ou Deny. Une machine qui sert au code d'inconnus peut autoriser son fournisseur de modèles, ses registres de paquets et GitHub, et refuser le reste. L'appel de l'exploit vers son serveur ne se connecte alors jamais.

La Security Timeline enregistre les verdicts du pare-feu, que vous ayez défini des règles ou non. Elle est toujours active, pour chaque machine, et une connexion vers un hôte dont le projet n'a jamais eu besoin y apparaît à côté de la session qui l'a ouverte.

Les push et les écritures attendent un clic

Le pire trophée de la liste du portable est le jeton gh, parce que des droits de push transforment une machine compromise en paquet compromis. Sur les nouvelles machines, chaque service protégé utilise Prompt before write. Un git push en HTTPS est une écriture, donc le proxy le retient et macOS affiche Allow write on "github.com" from workspace "…"? avec l'opération telle qu'elle est passée sur le réseau. La même politique couvre les API cloud, Kubernetes, les registres et les bases de données. Le dialogue est dessiné sur le Mac à partir de ce que le proxy a lu, si bien que le code de la VM ne peut ni y répondre ni en changer le texte.

La trace garde l'histoire

Une injection d'arguments commence par un appel d'outil qui a l'air anodin. Au niveau de traçage par défaut, AI request details, le proxy conserve chaque échange avec le fournisseur de modèles, chiffré sur le Mac, et le Trace Inspector décompose chacun en appels d'outils, commandes shell et lectures de fichiers. Quand ZDI publiera le bug en janvier, vous pourrez chercher dans vos traces la commande et l'argument qui l'ont déclenché, et l'enregistrement que vous consultez a été écrit sur le Mac, hors de portée de tout ce qui a tourné dans la VM.

Le nettoyage porte sur une seule machine

Si l'exploit a écrit quelque chose dans le répertoire personnel, Rewind home… le ramène au point de contrôle pris lors d'un démarrage précédent. Une machine signalée par le détecteur de compromission refuse de démarrer tant que vous n'avez pas choisi Wipe and Launch, qui reconstruit son disque et son répertoire personnel en conservant vos réglages et les vrais identifiants sur le Mac. Pour du code que vous voulez seulement regarder une fois, bromure-cli vm run --rm démarre une machine qui est supprimée, disque compris, à son arrêt.

Dans Bromure : l'évasion atterrit dans une VM, les sorties sont sur le MacVM de la machine (Ubuntu)Sandbox Codex : cassé par un argumentle code tourne sous l'user de la VMCe qu'il trouveANTHROPIC_API_KEY=sk-ant-api03-brm-…GH_TOKEN=ghp_… (substitut)~/.ssh : aucune clé privéeseul le home de la machineni home du Mac, ni autres projetsSwitch + proxy, sur le MacPare-feu : hôte inconnu → refusverdict dans la Security TimelineSubstitut hors périmètre → 451, pauseTrace : chaque appel et commande,chiffrée sur le MacDialogue macOS : Allow write on …?POST /acme/app.git/git-receive-packInternetfournisseur IAregistres de paquetsgithub.comhôte de l'attaquant :jamais contactéConservé sur le Mac, hors de la VMclés d'API et jetons OAuth · identifiants git et cloud · clés SSH · votre dossier · autres projets · traces
La même évasion dans une machine Bromure. Le sandbox de l'agent cède toujours, mais le code atterrit dans une VM avec son propre répertoire personnel, des identifiants de substitution et aucune clé privée. Ses sorties, ses dialogues d'écriture et sa trace sont sur le Mac.

Quelle que soit la porte ouverte

Le règlement de Pwn2Own exclut l'injection de prompt, les modes non sûrs et les identifiants stockés pour qu'une victoire mesure une seule chose : la frontière propre à l'agent. C'est le bon test pour un concours. Sur votre portable, les attaquants utilisent les trois chemins exclus.

La frontière de la VM ne dépend pas de la façon dont le code est sorti de l'agent. Un bug d'injection d'arguments, un README piégé qui convainc le modèle de lancer une commande, un fichier de test qui télécharge un implant, un développeur qui a coupé les demandes à 2 h du matin : chacun aboutit à du code qui tourne sous l'utilisateur de la VM, face aux mêmes substituts, au même pare-feu et aux mêmes dialogues sur le Mac. OpenAI livrera le correctif du bug d'Ireland à son propre rythme, et d'ici là le bug se heurte à la frontière de la VM comme les autres.

L'évasion atterrit dans une VM

Le code qui sort du sandbox de l'agent tourne sous l'utilisateur de la VM, avec le répertoire personnel de cette machine et les dossiers que vous lui avez partagés. Le dossier personnel de votre Mac, votre trousseau et vos autres projets ne s'y trouvent pas.

Les clés sont des substituts

Les vraies clés d'API, jetons git et secrets cloud restent chiffrés sur le Mac, et les clés SSH signent via un pont. Un substitut envoyé hors de son périmètre reçoit un 451 et met la machine en pause.

Les push exigent un clic sur le Mac

Avec Prompt before write, le réglage par défaut des nouvelles machines, un git push ou un appel cloud destructeur attend un dialogue macOS auquel la VM ne peut pas répondre.

L'enregistrement reste sur l'hôte

Le pare-feu de sortie, la Security Timeline et la trace tournent tous sur le Mac. Quand le bug sera publié, l'historique de chaque session sera là pour vos recherches.

Comptez sur le prochain

Pwn2Own reviendra au printemps, et les agents de code figureront de nouveau sur la liste, parce qu'un agent de code exécute des commandes sur la machine d'un développeur avec la portée de ce développeur. Une équipe arrivera avec un bug que personne n'a vu. Les éditeurs le corrigeront en moins de 90 jours, et le concours suivant remettra le compteur à zéro.

Continuez à mettre vos agents à jour, et faites-les tourner dans une machine où le trophée derrière le sandbox de l'agent est une VM aux clés de substitution. Pour comprendre pourquoi cette frontière se trouve sur l'hôte, lisez Le garde et le shell n'étaient pas d'accord et Onze tests réussis.