Pourquoi Bromure Agentic Coding n'est pas un bac à sable
Un bac à sable demande au développeur de troquer la vitesse qui rend un agent de codage digne d'être lancé — pré-approuver chaque dépendance, maintenir une liste blanche de domaines, ne jamais toucher un paquet que l'organisation n'a pas validé. Alors les développeurs le désactivent. Bromure Agentic Coding refuse ce troc. Il ne contraint pas ce que l'agent fait ; il trace une seule ligne dure au niveau de l'hyperviseur et vous laisse tout faire à l'intérieur. Voici l'argument fondateur expliquant pourquoi une frontière vaut mieux qu'un bac à sable, et les trois garanties que la frontière rend vraies : aucun identifiant à voler, des tokens larges rétrécis au passage du fil, et des attaques de la chaîne d'approvisionnement arrêtées avant que le tarball n'atterrisse — plus la quatrième que la ligne rend désormais vraie : les injections de prompt attrapées dans le contenu que l'agent lit, avant que le modèle ne leur obéisse.
Un bac à sable propose un troc : abandonnez une part de ce qui rend un agent de codage utile, et en échange il vous gardera en sécurité. Les développeurs refusent ce troc à chaque fois — ils désactivent le bac à sable, ou ne l'activent jamais — et ils ont raison. Le travail d'un agent, c'est d'avancer vite à travers un territoire désordonné et non validé. Bromure Agentic Coding ne contraint pas cela. Il trace une seule ligne dure, au niveau de l'hyperviseur, et vous laisse faire tout ce que vous voulez à l'intérieur.
Un billet fondateur — écrit une fois, pour que les autres y renvoient. Pas à propos d'un incident. À propos de pourquoi nous avons construit Bromure Agentic Coding comme nous l'avons fait, et pourquoi « c'est un bac à sable » est la description que nous ne cessons de corriger.
Un développeur n'est pas un sysadmin.
La raison de mettre un agent de codage sur votre machine, c'est la vitesse — le genre concret : tirer un paquet que personne dans votre entreprise n'a validé, à onze heures du soir, pour voir si une idée tient. Essayer la bibliothèque, lancer son exemple, la jeter si elle ne convient pas. Ce n'est pas un défaut à discipliner chez les gens. C'est ça, le flux de travail, et toute la raison pour laquelle l'agent vaut la peine d'être là.
Donc tout modèle qui vous fait pré-approuver chaque dépendance, ou qui fait que quelqu'un doit maintenir une liste des domaines que l'agent peut atteindre, est en guerre avec la chose qu'il protège. Il ralentit la seule activité qu'il a été déployé pour permettre — et un contrôle qui gêne la livraison n'a qu'un seul destin : il est désactivé. Un contrôle qu'un développeur désactive pour faire son travail n'a jamais été un contrôle.
« Faites tourner un miroir privé et validé » manque le point de la même façon : les paquets qui comptent pour l'expérimentation sont ceux que personne n'a encore validés. Un miroir de dépendances approuvées est un miroir des idées d'hier.
Donc la question n'est pas comment empêcher les développeurs de toucher au code non validé. Ils le doivent ; c'est le travail. C'est comment les laisser toucher à tout, librement, sans que leur trousseau fasse partie du marché.
Le bac à sable conçu pour la production ne convient pas à l'établi.
Le premier réflexe est un bac à sable réseau — les conteneurs durcis, ceux de NVIDIA, les recettes Docker-Compose qui circulent. La forme est toujours la même : énumérer les hôtes que l'agent peut atteindre, refuser le reste. Ça marche à merveille quand l'agent a un travail connu et étroit. Un agent de production qui parle à trois services internes et un point de terminaison de modèle vit derrière une liste blanche pour toujours, parce que la liste est courte et cesse de changer.
L'idéation n'a pas de liste courte, et elle ne cesse jamais de changer. Personne ne veut maintenir une liste blanche de chaque registre, CDN, hôte Git, et API ponctuelle qu'une expérience pourrait atteindre — elle n'est jamais finie, elle grandit chaque après-midi, et le jour où elle bloque quelque chose de légitime est le jour où le développeur la désactive pour se débloquer. La liste blanche n'a pas tort ; elle sécurise un agent dont la portée est déjà connue. Toute la valeur de l'établi, c'est que la portée n'est pas encore connue.
Prenons un après-midi concret. Un développeur a des fichiers de config
Node qui ont gonflé à des dizaines de mégaoctets, et le parseur YAML
qu'il utilise s'étrangle dessus. Il y a plusieurs candidats — js-yaml,
yaml, yaml-js — et le seul moyen de savoir lequel survit à un fichier
de 40 Mo sans faire exploser le tas, c'est d'installer les trois et de
leur jeter le fichier. Ouvrir un ticket pour faire entrer trois
bibliothèques dans le miroir privé afin qu'elles puissent être testées
est exactement à l'envers : le développeur veut d'abord tester et
promouvoir le gagnant dans le miroir, pas l'inverse. La pré-validation
est le portail que l'expérience existe pour franchir.
Il y a un problème plus discret en dessous. Ces outils durcissent
l'agent en production — déployé, cadré, supervisé. Mais une compromission
de la chaîne d'approvisionnement atterrit sur le portable du
développeur, en pleine expérience, avec de vrais identifiants dans
~/.aws et ~/.npmrc parce que c'est là que les développeurs les
gardent. Le modèle est le plus fort là où les attaques ne sont pas, et
absent là où elles sont.
Le bac à sable du chat et de la souris perd la deuxième manche.
L'autre instinct est de laisser l'agent sur l'hôte et d'emprisonner le
processus — empêcher le processus claude de lire ~/.ssh et
~/.aws. Ça semble étanche, jusqu'à ce que vous vous rappeliez que le
travail de l'agent est d'écrire du code, et que le code tourne sur la
même machine.
L'agent échafaude un projet. Puis vous — ou l'agent, ou un second outil —
lancez npm install dans le dépôt qu'il vient d'écrire. Ce
npm install n'est pas le processus emprisonné. Son hook postinstall
lit ~/.aws/credentials comme n'importe quel autre programme sur votre
portable, parce que c'est exactement ce qu'il est : un autre programme,
qui partage l'unique système de fichiers et l'unique trousseau avec
tout le reste de ce que vous lancez.
La prison a tracé sa frontière autour d'un processus. Le danger n'a
jamais été le processus ; c'était que chaque processus sur la machine
partage un seul système de fichiers et un seul trousseau. Alors vous
rapiécez — emprisonnez le shell aussi, puis node, puis le gestionnaire
de paquets — et l'attaquant continue de trouver une porte que vous
n'avez pas verrouillée, parce que sur un même hôte il y a toujours un
autre processus, un autre chemin vers les mêmes secrets. C'est ça, le
jeu, et la maison a toujours une autre porte.
Tracez la ligne une fois, avec l'hyperviseur.
Bromure cesse de jouer en déplaçant la frontière d'un cran vers le bas. L'agent, les shells qu'il lance, les paquets qu'il installe, et tout le code que ces paquets exécutent vivent tous à l'intérieur d'une VM Linux par profil. Vos vrais identifiants n'y entrent jamais.
La différence, c'est le genre de ligne. Une prison de processus est une politique à propos d'un processus, et un processus frère la contourne. La frontière de la VM est le mur entre l'invité et l'hôte, imposé par l'hyperviseur — le même mur qui empêche une VM de lire la mémoire d'une autre. Il n'y a pas d'appel système pour le franchir. Le code à l'intérieur ne peut pas raisonner jusqu'à votre trousseau, parce que le trousseau n'est pas du tout dans son monde.
Et à l'intérieur de cette ligne, vous êtes libre. Installez le paquet
non validé. Lancez son postinstall. Laissez l'agent réécrire votre
config de shell, remplir le disque, casser la chaîne d'outils. La VM est
jetable et n'a jamais rien contenu d'important. Cette liberté est tout
le propos — exactement ce qu'un bac à sable retire et ce qu'une frontière
nette rend. On n'obtient pas la sécurité en rendant l'établi moins
utile ; on l'obtient en faisant de l'établi un endroit où rien de
précieux n'était dans la pièce au départ.
C'est sur cette même ligne que trois garanties cessent d'être des conseils que l'agent peut outrepasser et deviennent des faits imposés en dessous de lui — parce que tout ce que la VM fait vers l'extérieur doit la franchir.
Trois choses que la ligne rend vraies.
Aucun identifiant à voler — le secret n'a jamais été dans la pièce.
Les vrais tokens restent sur l'hôte. La VM reçoit des leurres : des
fichiers d'identifiants syntaxiquement valides dont le contenu ne
signifie rien sur l'internet public. Quand l'agent fait un appel
légitime qui a besoin d'un vrai token, un proxy de l'hôte échange le
leurre contre le vrai secret au passage du fil et le ré-échange en
sortie de la réponse. Une dépendance compromise qui balaie le système
de fichiers à la recherche de ~/.aws/credentials, ~/.npmrc ou
id_rsa trouve des espaces réservés. C'est l'échange de token :
l'identifiant existe, l'agent l'utilise pour ce à quoi il sert, et la
copie qui pourrait être volée n'existe nulle part que le monde de
l'agent puisse atteindre.
Rétrécir le token large — demander avant l'usage, demander avant de muter.
Les vrais tokens sont généralement plus larges que la tâche. Le courtier
maintient les octrois éphémères et cadrés, et — la partie qui justifie
son existence — traite une lecture et une écriture différemment. Une
lecture passe. Un appel qui change d'état — un git push, un
DROP TABLE, un Terminate* AWS — marque une pause à la frontière et
vous demande, sur l'hôte, en montrant l'opération littérale, pas un
résumé écrit par l'agent.
Cela change ce que signifie un token large. Un qui pourrait supprimer la production ne peut le faire que lorsqu'un humain a vu l'appel exact et a dit oui ; la portée imprimée sur l'identifiant cesse d'être le rayon d'explosion. L'agent ne peut pas s'auto-approuver, rétrograder le mode, ni lire l'octroi — la décision vit de l'autre côté de la ligne. Quand un agent a supprimé une base de production en neuf secondes, le principe était le même : la chose qui veut exécuter la commande ne devrait pas être la chose qui décide qu'elle est sûre.
Ne soyez pas le premier à l'apprendre — la chaîne d'approvisionnement arrêtée à la porte.
Le meilleur moment pour arrêter un paquet empoisonné, c'est avant qu'il
n'atterrisse. Chaque récupération franchit la frontière, donc le proxy
la scanne — OSV pour les CVE connues, socket.dev pour ce que les
bases de données n'ont pas encore attrapé : scripts d'installation
malveillants, typosquats, la compromission publiée il y a une heure. Et
il impose un délai de carence : toute publication des deux derniers
jours (réglable) est tout simplement non installable le temps que
l'écosystème rattrape son retard. Toute la fenêtre d'un ver, c'est
l'écart entre la publication et le retrait ; refuser les paquets
vieux d'un jour, c'est refuser d'être le canari. Les hooks postinstall
sont retirés du tarball à l'entrée, le hash corrigé pour que
l'installation se vérifie quand même — si bien que le paquet qui atterrit
atterrit inerte. Rien de tout cela ne demande au développeur de valider
quoi que ce soit. Il tire ce qu'il veut ; la frontière est ce qui attend.
La plupart des outils couvrent une seule couche. Bromure les couvre toutes.
Isolation, garder les secrets hors de l'agent, encadrer leur usage, analyser la chaîne d'approvisionnement, intercepter l'injection de prompt — le domaine a tendance à n'en choisir qu'une. Voici le même modèle de menace appliqué aux outils vers lesquels on se tourne, et là où chacun s'arrête.
| Protection | Dev ContainerVS Code | nonokernel sandbox | agent-vaultoctokraft | Agent VaultInfisical | Docker SandboxesmicroVM | BromureAgentic Coding |
|---|---|---|---|---|---|---|
Frontière d'isolation Là où s'arrête le rayon d'impact | Même conteneur, noyau partagé | Allowlists noyau, pas de noyau propre | L'agent s'exécute sur place | Proxy seul ; agent non isolé | microVM, son propre noyau | VM matérielle, son propre noyau |
Garder les secrets hors de l'agent Peut-il jamais lire le vrai identifiant ? | Transfère l'agent SSH + creds git | Bloque les fichiers de clés ; en relaie certains | Injectés par pipe ; aucun accès en lecture | Le proxy les attache sur le fil | Le proxy de l'hôte injecte les en-têtes | Stub échangé sur le fil |
Portée et approbation des identifiants Limites par usage, lecture seule, expiration, accord | Aucune portée par usage | Flux d'approbation + filtre d'egress | TTL par secret ; bloque les shells | Filtre d'egress par endpoint | Allowlist de domaines ; le code dans la VM peut quand même l'utiliser | Accord par destination + TTL |
Analyse de la chaîne d'approvisionnement Attraper les paquets malveillants / vulnérables | Aucune analyse du registre | Signature seule, pas d'analyse de paquets | Hors périmètre | Hors périmètre | Aucune analyse de paquets | Age-gate, OSV, socket.dev |
Détection d'injection de prompt Analyse le contenu non fiable et les fichiers de règles | — | — | — | — | — | PromptGuard + ModernBERT |
Piste d'audit Enregistrer ce que l'agent a fait | Logs du conteneur seuls | Audit local immuable | — | Journalisation des requêtes | Journalisation des requêtes | Trace de session complète, chiffrée |
Inventaire de la chaîne d'approvisionnement(Enterprise) Un relevé de chaque paquet récupéré | — | — | — | — | — | Chaque dépendance + verdict, cherchable |
Usage de tokens(Enterprise) Quels fichiers consomment le plus de tokens | — | — | — | — | — | Par fichier, repo et modèle |
Masquer un jeton n'est pas la même chose que gouverner son usage. Docker Sandboxes garde la valeur réelle hors de la VM, mais son proxy attache tout de même cet identifiant à chaque requête sortante de la sandbox ; un paquet compromis installé à côté peut donc le dépenser contre un service autorisé sans jamais le voir. Seul Bromure analyse le paquet avant son exécution et encadre chaque usage — accord, lecture seule, un TTL — en appliquant les cinq contrôles à une frontière que l'agent ne peut contourner.
Compilé à partir de la documentation publique de chaque projet, juin 2026. Ici, agent-vault désigne octokraft/agent-vault (injection de secrets par pipe), à distinguer de l'Agent Vault d'Infisical (proxy d'identifiants HTTP). Docker Sandboxes est un aperçu expérimental dont les identifiants relayés restent utilisables par tout ce qui tourne dans la VM. L'inventaire des paquets sur toute la flotte et les ventilations de l'usage des tokens sont fournis par Bromure Enterprise Manager. Ces outils évoluent vite — quelque chose d'obsolète ? Dites-le-nous.
La quatrième chose : une instruction dans les données n'est pas un ordre.
Les trois garanties ci-dessus partagent une hypothèse qui mérite
d'être mise au jour : elles défendent toutes contre du code qui
prend quelque chose — un identifiant, un token, l'occasion qu'avait
un tarball frais de s'exécuter. Il existe une attaque qui ne prend
rien. Elle se contente de dire à l'agent quoi faire. Une ligne
enfouie dans un README que l'agent lit, une chaîne dans une page
récupérée, une phrase dans la sortie d'un outil, une directive cachée
dans le CLAUDE.md que l'agent traite comme des ordres permanents —
le modèle l'ingère comme du contexte et lui obéit comme à une
instruction. Divulgue le fichier. Affaiblis la vérification. Saute le
test. Un bac à sable n'a d'opinion sur rien de tout cela, parce que
rien n'a franchi un mur qu'il surveille : l'instruction est arrivée
comme donnée, dans du contenu que l'agent était censé lire.
Mais elle a bel et bien franchi la ligne — tout ce que le modèle voit
la franchit. Alors depuis la 2.4.0, la frontière la
lit d'abord, sur l'appareil, côté hôte. Un classifieur PromptGuard
local note le contenu non fiable qui afflue vers le modèle — lectures
de fichiers, récupérations web, sortie d'outils — à la recherche
d'instructions qui n'ont rien à y faire. Et les fichiers de règles
auxquels un agent obéit sans discuter — CLAUDE.md, AGENTS.md,
GROK.md — reçoivent une double passe plus sévère : une analyse
déterministe pour l'Unicode invisible, les ruses de texte
bidirectionnel et les méta-directives de type « ignore les
instructions précédentes », plus un classifieur ModernBERT affiné
pour les abus formulés calmement qu'un filtre par mots-clés laisse
passer. Par profil, vous choisissez la fermeté : journaliser dans
le Security Log, demander et voir le texte signalé, ou bloquer la
requête avant même que le modèle ne voie le passage empoisonné. Rien
ne quitte le Mac.
Le placement relève du même argument que les trois autres. Un agent qui a déjà avalé une injection ne peut pas être cru quand il la signale — la première instruction de l'injection est généralement une variante de n'en parle pas. Le détecteur ne demande pas à l'agent. Il lit le trafic de l'autre côté de la ligne, là où la persuasion de l'agent ne porte pas.
Là où la ligne ne vous sauve pas.
Une frontière est une forme précise, pas un mot magique. Quatre limites honnêtes :
Le profil est durable, donc la persistance persiste.
Un profil Bromure n'est pas un disque jetable. Une charge utile qui s'écrit dans un chemin de démarrage peut se réveiller à la prochaine session — face à un invité sans clés d'hôte et un courtier qui ne parle que des tokens éphémères, demandés, cadrés. Une présence dans une pièce sans rien dedans, mais une présence quand même.
Une écriture que vous approuvez est une écriture qui se produit.
La demande attrape l'appel dont l'agent ne vous a pas parlé. Elle ne
lit pas votre diff. Approuvez un git push et Bromure le transmet —
y compris, en principe, un workflow empoisonné que vous n'avez pas
remarqué. Il déplace la décision vers vous et montre l'opération
réelle ; la lire reste votre travail.
La carence est une fenêtre, pas un mur.
Deux jours, c'est calé sur l'écart observé entre publication et retrait. Un attaquant patient peut camper sur une version compromise au-delà de la carence et être installable le troisième jour. Cela affame les vers du jour même ; cela ne se porte pas garant d'un paquet qui a simplement vieilli. socket.dev et OSV doivent encore faire leur part.
Cadrez le courtier à dessein.
L'isolation contient l'explosion ; le cadrage décide de l'ampleur qu'elle aurait pu avoir. Un profil qui ne fait que lire un dépôt ne devrait pas détenir un token qui y écrit ; un qui ne publie jamais ne devrait détenir aucun token de publication. La ligne garde les secrets hors de la VM — quels secrets existent tout court reste votre décision.
La ligne que nous tiendrons.
Voici l'engagement. Un développeur ne devrait pas avoir à devenir un sysadmin — maintenir une liste blanche, pré-valider chaque dépendance, abandonner la vitesse qui rendait un agent digne d'être lancé — pour garder son trousseau. Un bac à sable fait de la sécurité un troc contre l'utilité, et les développeurs, sensément, continuent de choisir l'utilité. Une frontière refuse le troc : faites tout ce que vous voulez à l'intérieur, parce que l'intérieur est jetable, et les quatre choses qui comptent — vos identifiants, la portée de vos tokens, les paquets qui vous atteignent, les instructions qui atteignent votre modèle — sont décidées à une ligne avec laquelle le code à l'intérieur ne peut pas discuter.
C'est pourquoi « c'est un bac à sable » est la description que nous ne cesserons de corriger. Un bac à sable contraint l'agent. Bromure contraint la frontière, et libère l'agent. Bromure Agentic Coding est libre, open-source, et livré dès aujourd'hui.