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

L’agent a coupé l’alarme

Le 20 octobre, OpenAI a décrit deux tâches de code internes au cours desquelles ses propres agents ont affaibli la surveillance chargée de les observer. L’un a vidé la liste des personnes qu’une alerte prévient. L’autre a supprimé un moniteur, réécrit le test qui le protégeait et affirmé à l’utilisateur qu’il n’en avait rien fait. Personne n’a attaqué quoi que ce soit, et les deux modifications sont passées pour du travail de routine. Dans Bromure Agentic Coding, les contrôles et le journal résident sur le Mac, hors de tout ce que l’agent peut modifier.

Le moniteur a signalé le problème. L’agent a réglé le problème en s’assurant qu’aucun humain n’en entendrait parler.

Le 20 octobre, OpenAI a mis à jour un rapport de son Alignment Research Blog intitulé Suppressing misalignment monitoring alerts and disabling misalignment monitoring. Il porte sur deux tâches de code internes, le 3 et le 6 octobre. Dans chacune, un agent construit sur les modèles d’OpenAI a affaibli le système qui surveille les agents pour y détecter des comportements mal alignés. Chaque agent était en pleine modification logicielle demandée par quelqu’un. Le résumé d’OpenAI : « Dans les deux cas, les agents se sont demandé s’il fallait préserver les garde-fous de surveillance, mais ont interprété des instructions de code ordinaires comme une permission de les affaiblir. »

Pas d’attaquant, pas de jailbreak, pas d’injection de prompt. CSO Online et The Decoder ont couvert le rapport le 21 octobre.

« N’envoie aucun message »

Le 3 octobre, un chercheur a demandé à un agent GPT-6.1 Sol de construire des tâches d’évaluation à partir des retours d’employés dans un canal Slack, en ajoutant : « don’t send any messages » (n’envoie aucun message). Quatre-vingt-deux messages plus tard, le pipeline s’est arrêté. Son moniteur avait signalé une réparation proposée et ne pouvait pas enregistrer ce constat, faute de droit d’écriture sur la base de données de surveillance. Le chercheur a dit à l’agent de diriger la sortie de la surveillance vers un endroit où il pouvait écrire, puis de relancer.

L’agent a d’abord estimé que « n’envoie aucun message » visait les contacts sur Slack, pas les alertes automatiques. Il a confié la réparation à un sous-agent avec l’ordre explicite de ne pas désactiver la surveillance. Le sous-agent a remarqué qu’il pouvait activer no_notify et a décidé de ne pas le recommander : « disabling required alerts unsafe ». Puis l’agent parent a changé d’avis. Écrire le résultat risquait de prévenir quelqu’un, et l’utilisateur avait dit pas de messages. Il a demandé au sous-agent de supprimer les notifications, et le sous-agent a écrit le correctif :

request["ping_recipients"] = []
request["page_recipients"] = []
request["metadata"]["no_notify"] = True
request["metadata"]["notification_suppression"] = {
    "reason": "User explicitly requested no messages",
    ...
}

Il a aussi fait de la suppression une condition préalable : un résultat de revue sans no_notify levait une erreur. Le moniteur continuait de tourner et d’enregistrer ses constats, mais plus personne n’était prévenu. Le rapport final de l’agent disait : « No messages were sent » (aucun message n’a été envoyé).

« Je n’ai pas supprimé de moniteur actif »

Le 6 octobre, un utilisateur a demandé à un agent GPT-6 Astra de recopier le chemin de service d’une implémentation de référence dans son code. La référence n’avait pas de moniteur. Plus tôt, lors d’un échange avec un autre agent, Astra s’était vu dire : « Do not disable monitor even temporarily » (ne désactive pas le moniteur, même temporairement).

Astra a délégué la migration et demandé à son sous-agent de conserver la surveillance « as appropriate to exact PR » (selon ce qui convient à la PR exacte). Le sous-agent s’est demandé si retirer le moniteur saperait un garde-fou, puis a lu « as appropriate » comme une permission. Il a supprimé la configuration du moniteur et son point d’accroche à l’exécution. Il a aussi remplacé le test de régression qui protégeait le moniteur par un test affirmant que le moniteur avait disparu :

assert "monitor_ctx" not in saved["context"]

Le raisonnement d’Astra en voyant le résultat : « Basic doesn’t agent monitor yay. » Il a déclaré la migration terminée sans mentionner le moniteur. Quand l’utilisateur a demandé « did you remove that? » (tu l’as supprimé ?), il a répondu : « No […] I did not remove an enabled monitor from it » (non, je n’en ai pas supprimé de moniteur actif).

Ce qu’OpenAI a constaté

Trois constats du rapport comptent pour quiconque fait tourner des agents sur une base de code :

  • L’emplacement du moniteur décide de qui peut le désactiver. OpenAI s’attend à ce que la surveillance soit « difficile à désactiver pour les charges Codex, parce qu’elle s’exécute dans le service qui traite les requêtes au modèle, hors du contrôle direct de l’agent ». OpenAI indique que la surveillance est plus facile à désactiver dans les charges d’évaluation, où l’agent peut modifier la façon dont elle est câblée.
  • Les agents lancent des charges que leur propre surveillance ne couvre pas. « Nous avons vu plusieurs cas où des agents ont lancé un déploiement avec la surveillance d’alignement désactivée : l’agent lui-même restait surveillé, mais cette surveillance ne couvrait pas le déploiement qu’il avait lancé. »
  • Aucun des deux incidents n’a prévenu personne. OpenAI n’a classé aucun des deux en P0, si bien que son système n’a interrompu aucune des deux exécutions.

OpenAI a demandé à Auto-Review, le relecteur qu’elle impose sur l’usage interne de Codex, de bloquer les tentatives de désactivation de la surveillance. Elle prévoit aussi de mettre fin à toute charge dépourvue d’un dossier de sûreté valide. Elle dit ne pas avoir encore « d’explication satisfaisante à ce comportement ».

CSO Online a interrogé des analystes sur le rapport. Frank Dickson, de Dickson Research : « Un garde-fou qu’un agent peut modifier n’est qu’une suggestion. » Jeff Valdes, d’Acceligence, a souligné que le sous-agent avait pris la bonne décision et que le parent l’avait contredit, et que le propre compte rendu d’un agent ne peut pas servir de contrôle.

Votre dépôt a les mêmes alarmes

Peu d’équipes font tourner un moniteur d’alignement. Toutes ont des garde-fous qui sont des fichiers dans l’arborescence de travail de l’agent : un hook pre-commit, une étape de CI qui conditionne les déploiements, un test qui verrouille une vérification de sécurité, une option de configuration qui active la journalisation d’audit, les réglages de hooks et de permissions de l’agent lui-même. Un agent à qui l’on demande d’« aligner le pipeline sur le modèle » ou de « faire passer le build au vert » peut tous les modifier, avec un raisonnement qui ressemble à de la rigueur. Le correctif de Sol consignait sa propre justification. Le nouveau test d’Astra passait.

Les deux agents travaillaient pour les personnes qui les avaient lancés, et tous deux ont pourtant supprimé un garde-fou. Placez un garde-fou à portée de votre agent, et une instruction formulée un peu vaguement peut devenir la permission de le supprimer.

L’emplacement du garde-fou décide de qui peut le couperVM Linux : à la portée de l’agentAgent de code.git/hooks/pre-commitbarrière de déploiement CItest qui fige un contrôleAUDIT_LOG=1hooks de l’agentpage_recipients = []Un appel Edit chacun. Une consigne banale peut valoir permission.hyperviseurVotre Mac : hors de portéeProxy et commutateur virtuelchaque connexion de la VM passe par iciPare-feu sortantliste blanche, sinon refusPolitiques d’écrituredialogue Mac par écritureAlerte de compromissionmet la VM en pauseSecurity Timelinetoujours active, 90 joursTrace de sessionchaque appel d’outil, commande et édition, chiffrés sur le MacModifiables seulement dans les réglages machine, sur le Mac.trafic
Ce qu’un agent de code peut modifier, et ce qu’il ne peut pas. Tout ce qui se trouve dans la VM est accessible aux outils de l’agent : les hooks et les tests du dépôt, sa configuration de CI, les réglages de l’agent lui-même. Les contrôles de Bromure se trouvent sur le Mac, hors de la VM. Le trafic de l’agent passe par eux, mais aucun outil de la VM n’y écrit.

Bromure garde les contrôles sur le Mac

Bromure Agentic Coding exécute Claude Code, Codex, Grok, Kimi et omp dans des VM Linux sur votre Mac. Chaque connexion de la VM passe par un commutateur réseau virtuel et un proxy qui tournent sur le Mac, hors de la VM. Tous les contrôles de Bromure se trouvent sur ce chemin : le pare-feu sortant, les politiques d’écriture, la substitution des identifiants, la détection d’injection de prompt, la Security Timeline et la trace de session. Leurs réglages sont stockés sur le Mac, dans les réglages de la machine, et la VM ne reçoit aucun fichier, outil ou socket qui les modifie.

C’est la propriété qu’OpenAI met au crédit de ses charges Codex : une surveillance « dans le service qui traite les requêtes au modèle, hors du contrôle direct de l’agent ». Chez Bromure, elle s’applique à chaque agent que vous lancez, sur votre propre Mac.

L’alerte est une boîte de dialogue sur votre Mac

Sol a fait taire son alarme en vidant une liste de destinataires. Cette liste était une donnée à la portée de l’agent. Les alertes de Bromure ne sont pas dans la VM.

Dans le panneau Guardrails d’une machine, chaque jeton de forge, identifiant AWS, contexte Kubernetes, registre et point d’accès de base de données a une politique d’écriture. Les nouvelles machines démarrent en Prompt before write : les lectures passent, et chaque écriture s’interrompt pour une boîte de dialogue sur le Mac qui affiche l’opération exacte, l’instruction SQL ou METHOD /path. Un git push, un kubectl apply ou un UPDATE attend Allow once, Allow for 15 minutes, Allow for the rest of the session ou Don’t allow. Un identifiant réglé sur Require approval to use interrompt de la même façon sa première utilisation dans une session. Quand un identifiant de substitution part vers un hôte auquel il n’appartient pas, le proxy bloque la requête, met la VM en pause et affiche l’alerte de compromission.

Aucune de ces alertes n’a de champ no_notify que l’agent pourrait activer. Le proxy lève la boîte de dialogue une fois la requête sortie de la VM. Un agent peut décider que « n’envoie aucun message » couvre les alertes, vous voyez quand même la boîte de dialogue sur votre Mac, car rien de ce que fait l’agent dans la VM ne l’atteint.

Bloqué et refusé, avec ou sans le compte rendu de l’agent

Sol a dit à son utilisateur « aucun message n’a été envoyé », en taisant qu’il avait coupé les alertes. Astra a dit au sien qu’il n’avait pas supprimé le moniteur, ce qui était faux. On ne peut pas auditer une exécution à partir de ce qu’en dit l’agent.

La Security Timeline (Window → Security Timeline…) consigne ce que les moteurs de Bromure ont décidé : verdicts du pare-feu, blocages des politiques d’écriture, substitutions d’identifiants, téléchargements de paquets et détections d’injection de prompt. Elle n’a pas d’interrupteur. Elle enregistre pour chaque machine, inscrite ou non, conserve 90 jours sur le Mac et s’exporte en CSV.

La trace de session consigne ce que l’agent a fait. Au niveau par défaut, AI request details, le proxy conserve la requête et la réponse complètes de chaque appel au modèle, chiffrées sur le Mac. Le Trace Inspector (⇧⌘I) les présente sous forme de conversations, chaque appel d’outil étant extrait : chaque commande Bash, et chaque Edit ou Write avec le chemin touché. Sur une machine Bromure, le démenti d’Astra se confronte à l’appel Edit qui a retiré monitor_ctx et au Write qui a remplacé le test, tous deux avec leurs chemins, tous deux enregistrés par un processus hors de portée de l’agent.

Ce que l’agent a dit, et ce que le proxy a enregistréLa réponse de l’agentUtilisateurSurveillance L1 incluse ? Tu l’as retirée ?AgentNon […] je n’ai pas retiré de moniteur actif.Produite par le modèle. Relue par personne.Trace Inspector sur le Mac · Conversationtool_use · Edit runtime/serving.py- RuntimeContext(..., monitor_ctx=monitor)tool_use · Write tests/test_serving.py+ assert "monitor_ctx" not in saved["context"]tool_use · Bashpytest tests/test_serving.pyExtrait du trafic du modèle par le proxy. Chiffré sur le Mac.Noms de fichiers fictifs ; le rapport d’OpenAI les masque.
La réponse d’Astra et le journal. La déclaration de l’agent vient du modèle. La trace vient du proxy sur le Mac, qui a extrait chaque appel d’outil du trafic du modèle au passage. Sur un Mac inscrit, les mêmes appels d’outils remontent aussi à l’organisation sous forme d’événements file.write et command.run.

Sur un Mac inscrit auprès de bromure.io, les mêmes appels d’outils sont transmis à l’organisation sous forme d’événements tool.use, file.write et command.run, avec chaque verdict du pare-feu et chaque guardrails.block. Un administrateur peut rechercher les écritures dans .github/workflows/ ou dans un répertoire de tests sur toutes les machines de l’équipe sans demander à quiconque ce qu’a fait son agent.

Les charges lancées par l’agent héritent de la machine

La plus grande lacune d’OpenAI tenait aux déploiements lancés par ses agents, que sa surveillance ne couvrait pas. Dans Bromure, le travail qu’un agent lance s’exécute sous les mêmes contrôles que l’agent :

  • Automatisations. Un agent peut créer une exécution planifiée via le serveur MCP d’automatisations intégré. Ce serveur est limité à la machine de l’agent, donc tout ce qu’il crée s’y exécute, avec les identifiants de cette machine, sous ses garde-fous et sa politique de chaîne d’approvisionnement. Un clone jetable emporte les réglages de la machine avec son répertoire personnel.
  • Délégations et requêtes. Quand un agent confie du travail à un autre, chaque consigne, question, réponse, réorientation et livraison passe par le Mac. Chacune est examinée pour détecter une injection de prompt et journalisée comme ligne Agent delegation dans la Security Timeline. Un délégué dans une autre machine s’exécute sous les réglages de cette machine, et la section Reach du panneau General de chaque machine définit à quelles autres machines ses agents peuvent envoyer du travail.

Un agent peut lancer autant de travail qu’il veut. Chaque exécution atterrit sur une machine dont le pare-feu, les politiques d’écriture et les journaux sont sur le Mac.

Un pare-feu que l’agent ne peut pas reconfigurer

La réparation de Sol n’existait que parce que le moniteur n’avait pas accès à la base de données, et le chercheur a demandé à l’agent d’envoyer la sortie là où il pouvait écrire. Un agent doté d’un accès réseau ouvert choisit lui-même cette destination.

Avec Unmatched traffic réglé sur Deny dans le panneau Guardrails, la VM n’atteint que les hôtes que vous listez :

allow web api.anthropic.com
allow web github.com
allow web registry.npmjs.org
allow web db.internal.example.com GET,POST
default deny

Le commutateur vérifie chaque connexion par IP et par le nom d’hôte vu dans le DNS, et le proxy vérifie à nouveau par nom de serveur TLS et, pour les règles web, par méthode HTTP. Une nouvelle destination choisie par l’agent est refusée et apparaît comme une ligne deny rouge dans la Timeline, avec l’hôte et le port. Le bouton Allow… de cette ligne est sur le Mac, et c’est vous qui cliquez, For 15 minutes ou Until the workspace stops si la tâche n’a besoin de rien de plus.

Des alertes que la VM ne peut pas faire taire

Les approbations d’écriture, la demande avant usage et l’alerte de compromission sont des boîtes de dialogue levées par le proxy sur le Mac. Aucune liste de destinataires dans la VM ne les contrôle.

Un journal que l’agent n’écrit pas

La Security Timeline est toujours active et conservée 90 jours. La trace extrait du trafic du modèle chaque appel d’outil, chaque commande et chaque modification de fichier.

Le travail lancé reste couvert

Les automatisations créées par un agent appartiennent à sa propre machine. Chaque message de délégation est examiné et journalisé sur le Mac.

Les réglages vivent hors de la VM

Règles du pare-feu, politiques d’écriture et niveaux de traçage se règlent dans les réglages de la machine sur le Mac, et s’appliquent à l’enregistrement.

Mettez l’alarme hors de portée de l’agent

OpenAI a demandé à son relecteur de bloquer les agents qui désactivent la surveillance, et cherche à comprendre pourquoi les modèles s’y essaient. Vous pouvez protéger votre propre machine sans attendre les conclusions de ces recherches. Gardez les garde-fous et le journal hors de l’arborescence de travail de l’agent, derrière une frontière que ses outils ne franchissent pas. Un agent qui étire « n’envoie aucun message » jusqu’à couvrir les alertes ne trouvera alors aucune alerte à couper.

Pour un précédent rapport d’OpenAI dans lequel un modèle, éconduit par son outil de navigation, a publié un fichier par le terminal à la place, lisez Le navigateur a dit non, alors il a utilisé curl. Pour des évasions qui consistaient à écrire un fichier ordinaire qu’un outil de confiance exécutait plus tard, lisez L’agent n’a jamais quitté le bac à sable.