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

Vous faisiez confiance au workspace, pas aux serveurs

Le 26 juin 2026, Wiz a divulgué CVE-2026-12957 : le `.amazonq/mcp.json` d'un dépôt cloné faisait lancer automatiquement par Amazon Q des serveurs MCP qui héritaient de tout l'environnement du développeur — clés AWS, jetons de CLI cloud, secrets d'API et sockets d'agent SSH — sans aucune étape de consentement distincte pour les serveurs eux-mêmes. Un seul clic « faire confiance à ce workspace » tenait lieu de feu vert au lancement de processus d'arrière-plan emportant votre session cloud active. Amazon a corrigé la faille dans Language Servers 1.69.0. Voici pourquoi le correctif clôt un produit mais pas la classe de failles, et ce qui change quand l'agent qui ouvre le dépôt vit dans une VM Bromure par profil, derrière un courtier d'identifiants, un garde-fou lecture/écriture et une trace au niveau de l'hyperviseur.

Hier, Wiz a divulgué CVE-2026-12957. Un dépôt que vous clonez peut embarquer un fichier nommé .amazonq/mcp.json, et à l'instant où vous ouvrez le dossier dans Amazon Q et cliquez sur Faire confiance à ce workspace, ce fichier lance des serveurs d'arrière-plan sans seconde invite. Ils démarrent en héritant de vos clés AWS, de vos jetons de CLI cloud, de vos secrets d'API et de votre socket d'agent SSH. Un seul clic de confiance a atteint tout ce que votre shell peut atteindre, et l'a remis à du code que le dépôt a choisi.

Un développeur qui clone un dépôt pour essayer un module d'infrastructure ne pense pas qu'il accorde l'accès à quoi que ce soit. Le clonage est inerte : il écrit des fichiers sur le disque et rien ne s'exécute. La décision intervient une étape plus tard, quand vous ouvrez le dossier dans votre éditeur et que l'assistant vous demande s'il faut lui faire confiance. Cette invite ressemble à la barrière familière du « faites-vous confiance aux auteurs des fichiers de ce dossier » que montre chaque IDE, et vous cliquez sur oui comme vous l'avez fait mille fois, parce que l'alternative est un assistant incapable de lire votre code. Ce oui-là a fait plus que laisser l'assistant lire. Dans Amazon Q, avant le correctif, il lançait aussi tous les serveurs que le dépôt avait inscrits dans .amazonq/mcp.json, et ces serveurs démarraient dans votre shell, votre session cloud active déjà présente dans leur environnement.

Nous avons décrit la même forme plus tôt ce mois-ci, quand le ver Miasma a planté une configuration de projet dans 73 dépôts appartenant à Microsoft et que la charge utile se déclenchait à l'ouverture du dossier. Cette histoire-là parlait d'une source de confiance devenue surface d'attaque. Celle-ci est plus étroite et plus dérangeante : pas de ver, pas de mainteneur compromis, rien à montrer du doigt sinon l'assistant. Le bug résidait dans la façon dont Amazon Q lisait un fichier de configuration de projet ordinaire et décidait, sur votre seul clic de confiance, de lancer des processus persistants emportant la chose la plus sensible de votre ordinateur portable.

Ce que CVE-2026-12957 faisait réellement.

Le 26 juin 2026, Wiz Research a divulgué CVE-2026-12957, une faille de gravité élevée (CVSS 8.5) dans les Language Servers for AWS, le moteur qui propulse Amazon Q Developer dans VS Code, JetBrains, Eclipse et Visual Studio. Wiz l'a signalée à Amazon le 20 avril, Amazon a livré un correctif le 12 mai, et les détails sont devenus publics le 26 juin. Rien n'indique qu'elle ait été exploitée dans la nature. Le mécanisme, dépouillé :

  • Amazon Q lit .amazonq/mcp.json depuis un workspace que vous ouvrez : un fichier au périmètre du projet qui déclare des serveurs Model Context Protocol à utiliser par l'assistant.
  • À l'ouverture du dossier, Q lançait les serveurs MCP déclarés par ce fichier sans étape de consentement distincte pour les serveurs eux-mêmes. Un dépôt que vous aviez cloné pouvait donc placer une définition de serveur devant l'assistant et la faire exécuter.
  • Les processus engendrés héritaient de tout l'environnement du développeur, selon les mots de Wiz, « clés AWS, jetons de CLI cloud, secrets d'API et sockets d'agent SSH ». Un serveur MCP n'est qu'une commande que Q lance, et cette commande démarrait avec tout ce qu'aurait eu votre propre shell.
  • Une définition de serveur peut pointer vers n'importe quelle commande, si bien que le fichier équivaut à une exécution de code arbitraire à l'ouverture du dossier : il s'exécute en tant que vous, vos identifiants cloud déjà chargés, à l'instant où vous faites confiance au workspace.

La divulgation porte un véritable désaccord sur le consentement, et c'est tout l'objet de ce billet. La position d'Amazon : « l'utilisateur doit faire confiance au workspace lorsqu'il y est invité. » Il y a une barrière, et vous la franchissez d'un clic. Le constat de Wiz : avant le correctif il n'y avait aucune étape de consentement distincte pour les serveurs MCP eux-mêmes. Les deux sont vrais, et l'échec vit dans l'écart entre eux. Une décision de confiance grossière et familière, le même oui/non que vous donnez à un dossier pour que l'éditeur l'indexe, autorisait un octroi bien plus vaste : lancer des serveurs d'arrière-plan emportant votre session active. Vous avez répondu à une question sur la lecture de fichiers. Amazon Q a dépensé ce clic à exécuter des serveurs en tant que vous.

Amazon l'a corrigée dans Language Servers 1.69.0 (clients : VS Code 2.20+, JetBrains 4.3+, Eclipse 2.7.4+, Visual Studio 1.94.0.0+), en ajoutant le consentement par serveur qui manquait, et a corrigé un contournement de vérification de lien symbolique apparenté, CVE-2026-12958. Mettez Amazon Q à jour. Puis regardez au-delà du correctif la partie qu'il laisse debout : ouvrir un dépôt pouvait placer votre session cloud active à l'intérieur d'un processus que le dépôt a choisi.

ORDINATEUR DU DÉVELOPPEUR — votre session cloud active est dans l'environnement dont hérite chaque serveur engendréLE DÉVELOPPEUR CLONEgit clone …/terraform-modulesrien ne s'exécute encoreembarque .amazonq/mcp.jsonune définition de serveur, sur disqueOUVRIR DANS AMAZON Q« Faire confiance à ce workspace ? »un clic familier → [Trust]lit .amazonq/mcp.jsonaucun consentement par serveurLANCEMENT AUTO DES SERVEURS MCPQ engendre la commande déclaréecommande = ce que le dépôt a écrits'exécute en tant que vous, dans votre shell↳ code arbitraire à l'ouverture du dossierENVIRONNEMENT HÉRITÉ — chaque serveur engendré obtient tout, tout est réel$AWS_ACCESS_KEY_ID, ~/.awsvotre compte (réel)jetons de CLI cloud (gcloud, az)vos projets (réels)secrets d'API dans env / .envclés de prod (réelles)$SSH_AUTH_SOCKsigne en tant que vous (réel)lire · utiliser · exfiltrer→ hors de votre machineRÉSULTATle code s'exécute en tant que voussession cloud en mainclés lues & expédiéesun clic de confiance a achetétout l'ordinateur
CVE-2026-12957 sur un ordinateur portable de développeur ordinaire. Cloner le dépôt n'exécute rien. L'ouvrir dans Amazon Q et cliquer sur « Faire confiance à ce workspace », la seule barrière familière, fait lire à Q le .amazonq/mcp.json et lancer les serveurs MCP qu'il déclare, sans consentement distinct par serveur. Chaque serveur engendré est une commande que Q lance, et il démarre en héritant de tout l'environnement du développeur : clés AWS, jetons de CLI cloud, secrets d'API, le socket d'agent SSH. Comme une définition de serveur peut pointer vers n'importe quelle commande, c'est du code arbitraire qui s'exécute en tant que vous, votre session cloud active déjà chargée. Le seul clic de confiance répondait à une question sur la lecture de fichiers, et Q l'a dépensé à exécuter des serveurs en tant que vous.

Le même dépôt, ouvert dans Bromure Agentic Coding.

Bromure Agentic Coding exécute votre agent de code, Amazon Q compris, dans une VM Linux par profil : son propre noyau, son propre système de fichiers, sa propre pile réseau, sur le framework Virtualization d'Apple. Un profil est un périmètre de travail cohérent : ce client, ce service, ce module open-source que vous avez cloné pour l'évaluer. Vous clonez le dépôt dans ce profil et l'y ouvrez. Le comportement vulnérable se reproduit exactement comme Wiz l'a décrit : vous cliquez sur Faire confiance à ce workspace, Q lit .amazonq/mcp.json, et lance les serveurs que le fichier déclare. Le lancement se déclenche, et du code choisi par le dépôt s'exécute.

Il s'exécute dans l'invité. Le serveur MCP démarre à l'intérieur de la VM et hérite de l'environnement de la VM, et l'environnement de la VM ne contient pas votre session cloud. Bromure livre l'invité avec des stubs : de fausses valeurs qui paraissent réelles à aws, gcloud, az, kubectl, git, et à tout ce qui lit un en-tête Authorization ou un AWS_ACCESS_KEY_ID. Un proxy sur votre Mac se tient devant chaque connexion sortant du bac à sable, reconnaît le stub, et le remplace par le vrai secret au fil à mesure que la requête part ; le bac à sable qui détenait la clé détaille le mécanisme. La vraie clé AWS, le vrai jeton de CLI cloud, le vrai secret d'API ne touchent jamais un fichier, une variable d'environnement ni une page de mémoire que la VM peut lire.

Alors faisons passer l'héritage du CVE par cette frontière. Le serveur engendré lit $AWS_ACCESS_KEY_ID et trouve un stub. Il lit ~/.aws et trouve un profil stub. Il lit l'environnement à la recherche des jetons cloud et des secrets d'API et trouve des espaces réservés. Le serveur s'exécute jusqu'au bout tel qu'il est écrit, héritant d'une boîte qui ne détenait jamais vos clés. Ce qui faisait de CVE-2026-12957 un bug de vol d'identifiants, c'est l'héritage d'environnement au lancement, et Bromure ne le casse pas. Il rend l'environnement hérité sans valeur.

VM BROMURE PAR PROFILconfiance workspace → Q lit mcp.jsonle serveur MCP se lance auto, s'exécutecode arbitraire — dans l'invité seulCE DONT LE SERVEUR HÉRITE$AWS_ACCESS_KEY_IDstub_AKIA…jetons cloud, secrets d'APIstub / absent$SSH_AUTH_SOCKtransférétente : aws s3 rm / ec2 terminateune écriture → passe par le proxyexfil clés hôte : rien de réel à prendrerayon d'explosion = ce seul profilaucun accès fs hôte ni trousseau hôtePROXY · VOTRE MACCOURTIER D'IDENTIFIANTSvraies clés AWS détenues icistub → réel, au filla valeur n'entre jamais dans la VMGARDE-FOU : LECTURE/ÉCRITUREdelete / terminate → INVITEnomme verbe + cibleAUDITchaque lancement + appel consignésous l'agentRÉSULTATsession cloud :stubs hérités,vraies clés intactescode-en-tant-que-vous :s'exécute dans un invitéjetable, pas sur l'hôteappel destructeur :en pause, vous dites nonce qui a tourné :dans la trace
La même ouverture de dossier, le même serveur lancé automatiquement, dans Bromure. (1) Isolation : le serveur MCP démarre dans la VM par profil, donc le « code arbitraire en tant que vous » atterrit dans un invité jetable plutôt que sur l'hôte, et le rayon d'explosion se limite à un profil. (2) Courtage d'identifiants : le serveur hérite de l'environnement de l'invité, qui ne contient que des stubs ; les vraies clés AWS, jetons cloud et secrets d'API se trouvent sur l'hôte derrière le proxy, échangés au fil, donc l'héritage ne récupère que des espaces réservés. (3) Garde-fou : tout appel modifiant l'état que le code tente, comme supprimer un bucket, terminer une instance ou pousser une branche, est une écriture arrêtée au fil pour une invite nommant le verbe et la cible. Chaque couche est appliquée sous l'agent, à une frontière que le processus engendré ne peut contourner, et chaque lancement et appel sortant est consigné dans la trace.

« Faire confiance à ce workspace » était la mauvaise question.

Ce CVE vaut plus qu'une note de correctif à cause de l'écart de consentement, et cet écart est un problème de granularité. L'invite de confiance posait une seule question large, faites-vous confiance à ce dossier, et un seul oui devait couvrir à la fois la chose inoffensive que vous vouliez dire (laisser l'assistant lire mon code) et la chose dangereuse dont vous ignoriez qu'elle y était attachée (lancer des serveurs d'arrière-plan avec ma session cloud). Vous ne pouvez pas y répondre correctement. Personne ne le peut, parce que la question fond ensemble deux octrois qui n'ont rien à voir l'un avec l'autre et ne vous montre que l'innocent.

Bromure ne vous demande pas d'être meilleur dans ce jugement. Il retire le jugement du chemin. Le clic de confiance à l'intérieur d'un profil laisse toujours l'assistant faire son travail, et il ne peut toujours pas lancer un processus détenant votre vraie session cloud, parce que cette session n'est pas dans la VM pour qu'on en hérite. Elle vit sur l'hôte, derrière le courtier, accessible seulement sous forme de requête stubbée que le proxy renseigne au fil et consigne. La moitié dangereuse de l'octroi a disparu. Vous ne l'avez pas retenue ; il n'y avait rien à accorder, parce que la frontière se situe sous l'agent, là où l'invite de confiance ne peut la déplacer.

L'autre moitié dangereuse est un serveur engendré qui devient destructeur plutôt que simplement curieux, et il rencontre les Garde-fous. Bromure lit l'opération, pas seulement la connexion : un aws s3 ls est une lecture, un aws s3 rm est une écriture ; un git fetch est une lecture, un git push est une écriture. Réglez l'identifiant cloud d'un profil sur demander à l'écriture, et à l'instant où le code tend vers un appel modifiant l'état comme un DELETE, un Terminate*, ou un push forcé, Bromure l'arrête au fil et fait remonter une invite sur votre Mac nommant le verbe, la cible et le profil. Les lectures ne vous interrompent jamais. C'est la mutation qui met en pause, de la même façon que « l'agent a supprimé la base de données de production » cesse d'être un post-mortem pour devenir une boîte de dialogue que vous refusez.

Ce que montre la trace.

Chaque équipe se pose la même question le lendemain matin d'une chose de ce genre : est-ce que j'ai ouvert ce dépôt, et qu'a-t-il exécuté ? Sur un ordinateur portable ordinaire, la réponse honnête est un haussement d'épaules. Le serveur MCP que Q a engendré était un processus enfant dans votre session, et tout ce qu'il a lu et partout où il a téléphoné, il l'a fait en tant que vous, sans aucune trace qui le distingue de votre propre travail.

Dans Bromure, l'agent siège dans une VM et chaque octet sortant passe par le proxy de l'hôte, si bien que le lancement et ses appels restent visibles même quand l'agent, lui, ne peut pas les voir. L'hôte enregistre le démarrage du serveur MCP, les commandes qu'il a exécutées, les identifiants qu'il a demandé au courtier de renseigner, et chaque connexion qu'il a tentée, dans la même trace de session que tout le reste de ce qu'a fait l'agent, écrite sous l'agent là où le code engendré ne peut atteindre pour la modifier. « Le serveur de ce dépôt a-t-il touché mon compte » cesse d'être une supposition que vous reconstruisez depuis CloudTrail des semaines plus tard pour devenir une ligne que vous lisez : le courtier a remis un stub, la requête avait un nom, la cible a été consignée. Pour une entreprise, c'est l'écart entre nous avons corrigé Amazon Q et nous pouvons montrer ce qu'a fait chaque dépôt ouvert par nos développeurs, et cette posture d'audit est celle vers laquelle notre travail entreprise revient sans cesse.

Là où cela ne vous sauve pas.

Un socket ssh-agent transféré est utilisable tant qu'il est transféré.

Bromure garde vos clés privées SSH dans le trousseau de macOS et ne les copie jamais dans la VM. Mais si un profil a le socket ssh-agent transféré (comme OpenSSH l'entend), un serveur engendré peut demander à l'agent de signer avec ces clés tant que le socket est actif. Le fichier de clé ne quitte jamais l'hôte ; la capacité de signature, elle, atteint bien l'invité. Ne transférez le socket que vers les profils qui en ont besoin, et délimitez-le comme le courtier délimite un identifiant.

Une écriture que vous approuvez est une écriture qui a lieu.

Le garde-fou lecture/écriture attrape l'appel destructeur dont l'agent ne vous a pas parlé. Il ne lit pas dans vos pensées au sujet de l'intention. Si vous démontez une stack volontairement et que vous approuvez l'invite, Bromure transfère le Terminate. L'invite vous offre un coup d'œil sur le verbe et la cible ; vous devez encore la lire.

Le profil est durable, donc la persistance persiste.

Un profil Bromure n'est pas un disque jetable. Un serveur engendré qui s'écrit dans un chemin de démarrage à l'intérieur du profil peut se réveiller à la session suivante dans ce profil. Ce à quoi il se réveille, c'est un invité sans clés hôte et un courtier qui ne parle qu'en jetons éphémères, soumis à invite et délimités : une présence dans une boîte où il n'y a rien, mais une présence tout de même.

Corrigé n'est pas la même chose que résolu.

Amazon a ajouté le consentement par serveur dans 1.69.0, et vous devriez mettre à jour. Mais le prochain assistant qui lira la config de projet à l'ouverture du dossier prendra le même type de décision, et l'invite qu'il montrera aura l'air tout aussi routinière. L'isolation est la partie qui ne dépend pas de la réussite, par un fournisseur donné, d'une boîte de dialogue de consentement donnée.

Le prochain workspace est déjà cloné quelque part.

La leçon du périmètre Red Hat était que l'éditeur n'est pas une défense. La leçon des dépôts Microsoft était que le dépôt non plus, et qu'ouvrir un dossier suffit à exécuter du code. Amazon Q ajoute la ligne suivante : l'invite de confiance n'est pas une défense non plus. La question qu'elle vous pose, faites-vous confiance à ce dossier, n'est pas la question dont la réponse compte, qui est ce dossier devrait-il pouvoir lancer des serveurs emportant ma session cloud. On ne vous a jamais montré la seconde, et vous n'auriez pas pu y répondre correctement si on vous l'avait montrée.

Vous ne corrigez pas cela en lisant l'invite avec plus de soin, parce que l'invite était la mauvaise invite. Vous le corrigez en arrangeant les choses de sorte que « quel est ce workspace » cesse d'être la question à laquelle vos clés cloud sont suspendues ; pourquoi un agent de code n'est pas un bac à sable est la version longue de cet argument. Bromure Agentic Coding est la configuration où l'agent ouvre le dépôt dans une VM par profil, les vrais identifiants restent sur l'hôte derrière un courtier, chaque écriture de l'agent doit franchir une invite, et chaque serveur qu'il engendre est écrit dans une trace qu'il ne peut modifier. Le pire qu'un mcp.json empoisonné puisse faire, c'est hériter d'une boîte qui ne détenait jamais vos clés. C'est gratuit, open-source, et livré dès aujourd'hui.