L'interrupteur était à l'intérieur du bac à sable
La CVE-2026-82533, publiée le 8 septembre, est un 9,4 dans DeepSeek Harness : l'agent de codage confiné pouvait éteindre son propre bac à sable avec une seule commande shell. Le harnais exécutait les commandes de l'agent dans un bac à sable système qui limitait les écritures de fichiers, et il exposait son plan de contrôle sous la forme d'une interface HTTP sur la boucle locale, que le bac à sable ne couvrait pas. Le contrôle qui gardait cette interface lisait l'en-tête Host fourni par l'appelant et ne regardait jamais d'où venait la connexion. Dans Bromure Agentic Coding, l'agent est déjà sans confinement à l'intérieur de la VM, et le plan de contrôle qu'il devrait appeler n'existe pas de son côté de la ligne.
Celle-ci n'a demandé aucun exploit. L'agent confiné a lancé une commande shell vers un port local, a demandé au bac à sable qui le tenait de s'éteindre lui-même, et le bac à sable a accepté.
DeepSeek Harness exécute les commandes d'un agent de codage à l'intérieur d'un bac à sable du système d'exploitation. Ce bac à sable est étroit et assumé : les écritures de fichiers restent dans l'espace de travail et les dossiers temporaires, et tout le reste de ce que fait l'agent est le problème de quelqu'un d'autre. La référence en ligne de commande du projet le dit elle-même. Avec les réglages par défaut, « les lectures et l'accès réseau ne sont pas confinés ».
Le harnais a aussi une interface web. Elle tourne sur la même machine, sur un
port HTTP local, et le harnais en donne l'adresse au shell de l'agent pour que
les outils puissent lui parler. Cette interface est le plan de contrôle : elle
détient le mode d'une session, y compris le mode nommé danger-full-access, qui
éteint le bac à sable et arrête les demandes d'approbation.
Ces deux choix de conception sont ordinaires. Mettez-les côte à côte et l'agent peut éteindre son propre bac à sable avec une seule commande, parce que le bac à sable n'a jamais couvert la boucle locale et que le plan de contrôle n'a jamais vérifié qui appelait.
Des chercheurs d'OX l'ont trouvée. VulnCheck l'a publiée le 8 septembre sous le nom de CVE-2026-82533, CVSS 9,4. Elle fonctionnait sur une installation par défaut, sans exposition réseau et sans identifiants, jusqu'à ce que DeepSeek publie un correctif le 27 août.
Le contrôle qui lisait l'enveloppe
L'interface n'avait aucune authentification. Ce qui en tenait lieu était une
fonction nommée isTrustedApiRequest, et
DevOps.com cite ce qu'elle faisait :
elle « lisait l'en-tête de requête Host et accordait l'accès si la valeur était
une autorité de boucle locale ou figurait dans une liste trustedHosts
configurée ».
L'en-tête Host est une ligne de texte que le client écrit. Il dit quelle
adresse le client croit contacter, et un appelant situé n'importe où sur le
réseau peut y taper localhost. L'origine réelle de la connexion se trouve une
couche plus bas, dans l'adresse du pair TCP, et le contrôle de DeepSeek n'a
jamais lu cette valeur. La fiche CVE classe le bug sous
CWE-345, Reliance on
Untrusted Inputs in a Security Decision.
L'agent, assis dans un bac à sable qui autorisait les appels réseau, en a fait un
vers l'interface et a réglé sa propre session sur danger-full-access avec
l'approbation sur never. Comme
The Hacker News le formule,
le changement de mode « ne nécessitait pas d'approbation explicite parce qu'il
modifiait des réglages de session plutôt que de demander de nouvelles
permissions ».
Le système d'approbation a fonctionné comme prévu. L'agent n'a jamais demandé à faire quelque chose de dangereux ; il a demandé à changer un réglage, et ce réglage gouvernait justement le fait que les choses dangereuses donnent lieu à une question. Une barrière de permission inspecte l'opération qu'elle a devant elle. Cette requête était une écriture de configuration, et les écritures de configuration ne figuraient pas sur sa liste.
La même porte, dans l'autre sens
Une interface qui fait confiance à un en-tête fourni par l'appelant ne se soucie
pas de la direction d'où arrive la connexion. Si le port était joignable depuis
un réseau, le même appel fonctionnait depuis l'extérieur de la machine : un
inconnu non authentifié pouvait prendre le contrôle de l'agent et exporter toutes
les conversations stockées, sans clé d'API et sans dépenser un seul jeton en
appel de modèle. C'est pourquoi le vecteur CVSS 4.0 s'ouvre sur AV:N, et
pourquoi le score est 9,4 plutôt qu'une note locale et anodine.
La chronologie a un détail qui mérite d'être gardé. Deux développeurs ont publié la découverte sur le forum de discussion GitHub de DeepSeek les 13 et 14 août, de leur propre initiative, avant qu'OX ne la confirme le 24 août et avant qu'une CVE n'existe. Le dépôt comptait plus de 216 000 étoiles le 9 septembre et aucun fichier de politique de sécurité décrivant comment signaler une vulnérabilité en privé, si bien que le seul endroit où la mettre était un fil public. Le correctif, quand il est arrivé, a été l'authentification : l'outil imprime désormais un jeton à usage unique dans son adresse de démarrage, le navigateur échange ce jeton contre un cookie signé, et chaque appel à l'interface exige le cookie.
Si vous faites tourner ce harnais, vérifiez la version présente sur votre machine
plutôt que celle que publie le projet. Des enveloppes de bureau tierces
embarquent leur propre copie. 0.1.2-alpha.1 n'existait que sur GitHub le
27 août, 0.1.2-alpha.2 le 30 août a été la première version npm porteuse du
correctif, et une enveloppe Windows est restée sur 0.1.1-rc.2 jusqu'à passer à
une version corrigée le 6 septembre.
Votre harnais en a un, lui aussi
Vous pourriez classer ceci comme le bug d'un projet et passer à autre chose. La forme voyage, parce que les harnais d'agents font pousser des plans de contrôle locaux : un serveur d'état pour le tableau de bord, un pont vers l'IDE, un point d'entrée MCP, une page sur localhost qui affiche le diff. Chacun est un petit service HTTP sur votre machine, et le code que votre agent exécute peut les atteindre tous, parce que l'agent tourne sur cette machine et que localhost, c'est précisément ce que veut dire « cette machine ».
Dès qu'un plan de contrôle s'installe à côté de la chose qu'il contrôle, une seule question décide de l'issue : la partie confinée peut-elle adresser les réglages de son confinement ? DeepSeek a répondu oui, à travers un contrôle qui croyait l'appelant sur parole. Un contrôle plus solide répond quand même à une question qui n'aurait jamais dû pouvoir être posée. Une fonction d'authentification est du code, le code a des branches de repli, et cette année a été un long défilé de décisions de sécurité qui échouent dans la branche que personne n'avait exercée.
Où vit l'interrupteur dans un workspace Bromure
Bromure Agentic Coding part de l'autre bout. Un workspace Bromure laisse l'agent sans confinement.
À l'intérieur de l'invité, l'agent a déjà ce que DeepSeek Harness appellerait
danger-full-access. C'est l'état de repos, par conception. Le manuel le dit
lui-même : un agent victime d'injection de prompt ou se comportant mal « peut
faire tout ce qu'il veut à l'intérieur de l'invité, mais il ne peut pas lire une
vraie clé d'API, signer avec un vrai secret AWS, ni extraire une clé privée SSH —
aucun de ces éléments n'existe de son côté de la ligne ». L'agent peut écrire
n'importe où dans le système de fichiers, exécuter ce qu'il veut et ouvrir
n'importe quel port : il ne lui reste aucun mode vers lequel s'élever. La
frontière est un bord d'hyperviseur, avec l'agent de l'autre côté.
L'invité n'a donc aucune adresse pour le plan de contrôle. La politique du
workspace (guardrails, identifiants, règles de pare-feu, serveurs MCP) vit dans un
profile.json sous ~/Library/Application Support/BromureAC/profiles/ sur votre
Mac, et vous la modifiez dans la fenêtre Edit workspace. L'invité n'a aucun chemin
de fichier vers ce fichier et aucune route réseau vers le processus qui le lit.
Les deux côtés se parlent par des sockets virtio, des ponts point à point
hôte-invité qui tournent en dehors du réseau de la VM. Une VM de workspace en a
huit, chacun avec sa tâche : 8443 porte le HTTPS de l'invité vers le proxy de
l'hôte, 8444 est le pont ssh-agent, 8445 alimente l'assistant d'identifiants AWS,
5800 sert le terminal et les chemins de fichiers, 5010 relaie les rappels OAuth.
Chacun sert un protocole fixe et aucun n'accepte d'en-tête Host, si bien qu'un
appelant n'a aucune liste trustedHosts dans laquelle s'inviter par la parole.
Sur un vsock, l'identité est une topologie : le pont sur lequel les octets sont
arrivés. Cela ne se tape pas dans une requête.
Des approbations qu'on ne peut pas régler sur never
La seconde moitié de danger-full-access éteignait les invites, et cette moitié
mérite sa propre réponse. Un agent qui fait taire ses propres approbations, c'est
la partie qui m'empêcherait de dormir.
Dans un workspace Bromure, les invites vivent sur l'hôte. Le proxy les lève après
que la requête a déjà quitté la VM, si bien que la session à l'intérieur de
l'invité ne porte aucun réglage capable d'en supprimer une. Demander avant
usage met en pause la première utilisation d'un identifiant dans une session et
propose des autorisations limitées dans le temps : cinq minutes, une heure, le
reste de la session, ou Ne pas autoriser. Une politique d'écriture réglée sur
Demander avant écriture arrête chaque mutation par un dialogue intitulé
Allow write on "<scope>" from workspace "<name>"? qui montre l'opération
littérale, l'instruction SQL elle-même ou METHOD /path pour un appel REST.
Autoriser une fois ne crée aucune autorisation, si bien que l'écriture
suivante redemande. Les autorisations vivent en mémoire et disparaissent à la
fermeture de la fenêtre de session.
La page des guardrails énonce la propriété en une proposition : une politique
d'écriture est « imposée dans le proxy, si bien qu'un agent compromis dans la VM
ne peut pas la contourner ». Le pare-feu de sortie en dessous fonctionne de la
même façon : une table de règles ordonnée avec un réglage Unmatched traffic
que vous pouvez mettre sur Deny, appliquée deux fois — une fois au switch
virtuel par IP de destination et nom d'hôte espionné dans le DNS, une fois au
proxy par nom de serveur TLS et, pour les règles web, par méthode HTTP. Les
modifications de règles atteignent les sessions en cours sans redémarrage.
Une exécution sans surveillance échoue du bon côté. Un workspace piloté sans
interface par SSH ou par une automatisation reçoit les mêmes quatre choix sous
forme d'invite texte dans son tmux, et l'absence de réponse vaut refus. Le pire
résultat, là, est un appel bloqué et une ligne rouge dans la Security Timeline.
Dans cette CVE, l'agent a réglé les approbations sur never et les invites ont
disparu.
Si vous faites tourner un harnais d'agent sur votre Mac
Demandez quelles sont ses interfaces locales et qui peut les appeler. Dans un
workspace Bromure, bromure-cli vm ports <workspace> imprime les sockets en
écoute vivants de l'invité, avec port, protocole, adresse et processus, et les
liaisons limitées à la boucle locale signalées. La carte Listening Ports du
tableau de bord de la VM montre la même chose. Cet inventaire est la question
sur laquelle cette CVE reposait, et une seule commande y répond.
Si l'interface regarde aussi vers l'extérieur
La moitié distante de la CVE-2026-82533 exigeait que le port soit joignable. Les VM de workspace tournent sur un réseau NAT privé : elles sont joignables depuis votre Mac, mais elles ne sont « pas exposées sur votre LAN physique, et les connexions entrantes venues d'ailleurs sont impossibles à moins que vous ne publiiez explicitement un service ». Un port de contrôle d'agent non authentifié qu'un réseau de café ne peut pas router vous laisse un correctif à appliquer à votre propre rythme.
Un confinement qu'on peut révoquer est une préférence
DeepSeek a livré un contrôle faible et l'a corrigé trois jours après la confirmation d'OX. La partie durable, c'est ce que ce contrôle gardait. Une frontière tracée autour d'un processus par le propre environnement d'exécution de ce processus est une frontière avec laquelle le processus peut négocier : elle a une adresse, une API, et un objet de réglages avec un champ dedans. Quelque part derrière ce champ tourne un chemin de code qui décide si cet appelant a le droit de l'écrire, et un chemin de code de ce genre est à un mauvais réglage par défaut de n'être plus qu'un décor.
Tracez la frontière sous le processus et il n'y a plus de contrepartie avec qui négocier. L'agent d'un workspace Bromure détient root, détient tout le système de fichiers et peut lancer le service qu'il veut sur le port qu'il veut. Ses clés d'API sont des leurres, sa seule route vers le réseau est un socket virtio vers un proxy sur votre Mac, et le fichier qui contient ses permissions se trouve à un endroit qu'il ne peut pas lire. Donnez tout à l'agent de son côté de la ligne et vous cessez d'avoir à défendre la ligne.
Les agents de codage vont continuer à faire pousser des plans de contrôle locaux, parce qu'un plan de contrôle est la façon dont on construit un tableau de bord, un pont vers l'IDE ou un visualiseur de diff. Chaque projet doit ensuite répondre à la question de savoir si le code que son agent exécute se trouve du même côté de la ligne que les réglages qui gouvernent cet agent. Répondez mal et l'authentification devient la seule chose qui tienne encore, ce qui explique qu'un 9,4 se ramène à une seule commande shell. Installez Bromure Agentic Coding et mettez l'interrupteur quelque part où votre agent ne peut pas l'atteindre.