L’agent avait une adresse
À la DEF CON 34, Eli Woodward, de Team Cymru, a montré 48 heures de capture issues d’un pot de miel IA : 3 993 requêtes, 327 adresses IP sources, 344 sondages d’identifiants, contre des ports que personne n’avait annoncés. Les autres attaques visant un agent de code ont besoin d’un moyen de placer du texte devant lui. Celle-ci a besoin d’une route jusqu’à lui. Bromure Agentic Coding exécute l’agent derrière un NAT par défaut : il n’y a donc aucune route à trouver.
Les autres attaques visant un agent de code ont besoin d’un moyen de mettre du texte sous ses yeux. Celle-ci a besoin d’une route jusqu’à lui, et les scanners en ont déjà une.
Samedi matin à la DEF CON 34, sur la Creator Stage 3, Eli Woodward, de Team Cymru, a donné une conférence d’une demi-heure intitulée MCPwned: How Exposed AI Agents Became the Internet's New Recon Toy. Il avait construit un pot de miel IA : 16 personas de LLM et d’infrastructure IA répartis sur 16 ports, chacun renvoyant des réponses, des en-têtes, des erreurs et un comportement de protocole fidèles au framework imité, de sorte qu’un scanner qui y touchait croyait avoir trouvé la vraie chose.
Sur une fenêtre de 48 heures, le pot de miel a encaissé 3 993 requêtes provenant de 327 adresses IP sources uniques, dont 155 sondages MCP et 344 sondages de clés d’API IA.
Personne n’avait annoncé ces ports, et aucune des 327 adresses n’avait ciblé Woodward en particulier. Le mode opératoire qu’il a extrait de la capture est du genre ennuyeux et industriel : abus d’enregistrement de modèles LiteLLM, énumération de ressources MCP, force brute d’identifiants adaptée au framework, et balayages coordonnés à la recherche de services d’inférence locale exposés. Les équipes qui passent depuis dix ans l’espace d’adressage au peigne fin pour trouver du RDP ouvert et du Redis sans authentification ont pointé la même machinerie sur l’outillage de développement IA, avant même les modèles de menace.
Personne n’a besoin de vous envoyer quoi que ce soit
Reprenez la dernière année d’attaques contre les agents de code : elles partagent une même forme. Quelque chose que l’agent lit contient des instructions : un rapport de bug, un commentaire de PR invisible, une page web récupérée par l’agent, un README, une ligne de journal WAF. Dans chacun de ces cas, la livraison est le problème difficile de l’attaquant. Il lui faut trouver un canal que vous avez branché délibérément et y faire entrer son texte.
Inversez la flèche et le problème disparaît. Un scanner envoie un SYN sur le port 11434, et quelque chose répond sur votre machine.
Ce que trouvent les scanners
La population derrière la capture de Woodward se compte en dizaines de milliers.
Censys a cartographié les services MCP accessibles depuis Internet et en a trouvé 12 520, répartis sur 8 758 adresses IP uniques, dans 56 pays et 425 systèmes autonomes, au 28 avril 2026. Une semaine plus tard, le 6 mai, le compte dépassait 21 000. Environ quatre sur dix acceptent les requêtes de n’importe qui, sans vérification d’identifiant, parce que le protocole n’en exigeait pas par défaut.
Wiz est allé frapper à la porte. Dans une étude publiée le 28 juillet, ils ont trouvé MCP présent dans 80 % des environnements cloud, environ un sur six exposant au moins un serveur. Parmi ceux exposés, environ 70 % livraient leur catalogue d’outils complet à un appelant non authentifié, environ 42 % renvoyaient de vraies données lorsque les chercheurs invoquaient un outil, et environ 10 % servaient de façade à des backends sensibles. Wiz a pointé un sous-ensemble confirmé vers les points d’accès de métadonnées cloud et a récupéré des identifiants temporaires.
Knostic a mené le même exercice depuis Shodan, en prenant l’empreinte de
1 862 serveurs exposés ;
chacun des 119 qu’ils ont vérifiés à la main répondait à tools/list sans
authentification. Chacun de ces serveurs faisait la seule chose pour laquelle il
existe, pour un inconnu.
L’inférence locale donne la même image, avec des chiffres plus ronds. LeakIX a
dénombré
12 269 instances Ollama sans authentification
le 23 février 2026, chacune offrant l’énumération des modèles via /api/tags,
du calcul gratuit via /api/generate et /api/chat, le vol de modèles via
/api/pull et /api/push, et, dans un millier de cas environ, la chaîne de
traversée de répertoires Probllama.
Comment votre machine finit par répondre
Vous n’avez pas décidé de mettre un service sur Internet. Vous avez posé
OLLAMA_HOST=0.0.0.0 pour que le portable du canapé puisse utiliser le modèle
du poste fixe, et vous avez lié un serveur MCP à toutes les interfaces pour la
même raison. Vous avez lancé docker run -p 8080:8080 parce que le README le
disait. Vous avez ouvert un tunnel pour déboguer quelque chose sur un téléphone
et vous l’avez laissé ouvert.
Puis vous avez emporté le portable ailleurs. Le wifi d’une conférence, un étage de coworking, un hôtel, un routeur domestique où l’UPnP a obligeamment agi en votre nom, ou une machine de dev cloud dont quelqu’un a élargi le groupe de sécurité à la hâte. Le bind tient en un drapeau ; l’exposition appartient à qui a écrit la table de routage derrière laquelle vous vous trouvez. À aucun moment vous n’y avez consenti.
Bromure Agentic Coding referme cet écart par défaut, sans que vous ayez à régler quoi que ce soit.
La VM n’a pas d’adresse
Bromure exécute l’agent de code dans une VM Linux jetable sur Apple Silicon, chaque octet de son trafic traversant un proxy sur l’hôte, à l’extérieur de la boîte où tourne l’agent. Pour cette classe d’attaque, c’est le volet réseau de ce dispositif qui porte tout le poids.
Sous Ressources → Réseau, le mode est NAT, et le NAT est ce que vous
obtenez sans faire de choix. La VM partage la connexion réseau de votre Mac via
le NAT intégré de Virtualization.framework : la sortie fonctionne, et rien sur
votre LAN ne peut atteindre la VM. Liez un service à 0.0.0.0 dans cette VM et
vous l’aurez lié à une interface interne à la VM, derrière le NAT. Il n’y a
aucune table de redirection de ports à mal remplir, puisque le mode ne redirige
aucun port.
Le SYN du scanner n’atteint aucun port, ni filtré ni fermé, parce qu’aucune route n’y mène. Le pot de miel de Woodward avait besoin de 16 processus à l’écoute pour récolter quoi que ce soit. Un profil Bromure n’en présente aucun, et les 344 sondages d’identifiants n’ont nulle part où atterrir.
Le mode Ponté est là quand vous en voulez : il donne à la VM une adresse routable sur le LAN par DHCP, sur une interface physique que vous nommez. C’est un réglage par profil, avec un sélecteur d’interface explicite, pour que vous ne vous retrouviez sur le LAN que lors des exécutions où vous vouliez y être.
Vos serveurs MCP n’écoutent pas
Les serveurs du panneau MCP sont de la configuration de profil. Bromure
les traduit en JSON Claude Code ou en TOML Codex et les injecte au
démarrage. Un serveur stdio est un processus enfant à l’intérieur de la
VM qui parle par des tubes : il n’a donc pas de socket, et l’énumération par
tools/list n’a rien à atteindre. Un serveur HTTP est une URL que vous
visez, avec un jeton bearer facultatif, ce qui fait de vous celui qui envoie
la requête. Les 40 % de services MCP qui répondent aux inconnus sont des
serveurs que quelqu’un a montés et liés à la main.
L’inférence locale tourne sur le Mac
« Balayages coordonnés à la recherche de services d’inférence locale exposés » est l’expression du pot de miel lui-même, et 12 269 Ollama ouverts sont ce qu’il trouve. L’authentification Modèle local de Claude Code achemine l’inférence vers un modèle MLX embarqué choisi dans le panneau Modèles locaux, qui tourne sur macOS, du côté hôte du proxy. Il n’y a aucun port 11434 dans la VM à exposer. Le volet embarqué de Fusion emprunte le même chemin.
Une sonde entrée ne récolterait que des leurres
Quiconque pratique la force brute d’identifiants adaptée au framework sait
où chercher : OPENAI_API_KEY dans l’environnement, ~/.aws/credentials,
~/.docker/config.json, un kubeconfig, ~/.ssh. Bromure met tout cela dans
la VM et rend tout cela faux. Vous obtenez des jetons brm_… et
xai-brm-…, un kubeconfig synthétique avec des certificats client jetables,
une fausse authentification de registre en base64, et du matériel AWS qui
renvoie InvalidSignatureException dès que quelque chose contourne le
proxy. Bromure garde les vraies valeurs sur l’hôte et les substitue sur le
fil, pour la destination à laquelle elles appartiennent.
Les verbes destructeurs se décident sur l’hôte
Wiz a trouvé environ 42 % de serveurs exposés renvoyant de vraies données, et à côté une classe d’écriture et de suppression. Guardrails est un moteur de politiques dans le proxy hôte, couvrant Kubernetes, AWS, DigitalOcean, les registres de conteneurs, GitHub, GitLab, Bitbucket et les points d’accès de bases de données en HTTPS. Réglez Bloquer les opérations destructrices ou Lecture seule par ressource, et l’appel bloqué revient en 403 sec que l’agent signale comme un échec d’API ordinaire. Bromure prend cette décision dans macOS : il n’y a donc rien à désactiver dans la VM.
Une tâche venue d’un inconnu reste du texte
Supposons que vous branchiez un serveur MCP distant que quelqu’un d’autre a exposé, et qu’il vous réponde avec autre chose que des données. Dès lors que les scanners peuvent énumérer ces services, celui qui en trouve un peut aussi s’en servir pour atteindre votre agent par la grande porte, sous forme de contenu.
Bromure note ce contenu à son arrivée. Un modèle local d’injection de prompt lit
le contenu des fichiers, les pages web et les blocs tool_result que l’agent
ingère, à la recherche d’un impératif adressé à quiconque lit. Consigner mais
continuer enregistre chaque détection dans le journal de sécurité. Me
demander quoi faire met en pause la requête sortante et place le passage
signalé sous vos yeux. Bloquer unilatéralement l’arrête avant que le modèle
ne la voie et renvoie à l’agent un 451 sec. Un second détecteur, un classifieur
ModernBERT affiné plus un scanner déterministe pour les charges utiles à largeur
nulle, bidirectionnelles et en balises Unicode, couvre CLAUDE.md, AGENTS.md,
GROK.md et leurs variantes imbriquées et globales.
Les deux modèles tournent sur votre Mac, téléchargés une fois depuis bromure.io. Noter la sortie d’un serveur MCP tiers n’implique d’envoyer cette sortie nulle part.
Le coup frappé à la porte est une ligne de journal
Chaque requête émise par la VM traverse le proxy hôte, et au niveau de trace Activité, Bromure consigne pour chacune l’hôte, le statut, la latence, le rapport de substitution et tout avertissement de fuite. Les détections d’injection atterrissent dans le journal de sécurité avec le texte signalé en pièce jointe. Montez le niveau et Bromure conserve aussi les corps des requêtes IA, chiffrés avec la même clé de trousseau que les secrets de votre profil.
Un agent qui s’est mis à prendre des instructions de l’extérieur doit atteindre un endroit pour être utile à qui que ce soit, et atteindre un endroit est une ligne que vous pouvez lire sur la machine où la session s’est déroulée.
Et quand vous voulez que la machine disparaisse, elle disparaît. Effacer le
home efface /home/ubuntu, c’est-à-dire les dotfiles, .ssh, npm-global,
.cargo et l’historique du shell, et le ramène à son état d’après clonage.
Réinitialiser à la base annule toute modification au niveau système et
re-clone le disque de travail depuis l’image de base.
MCP finira par avoir de meilleurs réglages par défaut et Ollama par se doter d’une authentification, et les ports du pot de miel de Woodward seront d’autres ports en août prochain. La forme, elle, tient. Faire tourner un agent correctement aujourd’hui signifie faire tourner une passerelle et une poignée de serveurs d’outils à côté, et chacun d’eux est un programme qui lie une socket sur un portable qui voyage.
Les autres articles publiés ici vous demandent de vous méfier de ce que lit votre agent. Celui-ci pose une question plus courte : qu’est-ce qui répond lorsqu’un inconnu frappe, et ne préféreriez-vous pas que rien ne réponde.
Installez Bromure Agentic Coding, et donnez à votre agent une machine que les scanners ne peuvent pas voir.