Confiaste en el espacio de trabajo, no en los servidores
El 26 de junio de 2026, Wiz reveló la CVE-2026-12957: el `.amazonq/mcp.json` de un repositorio clonado hacía que Amazon Q lanzara automáticamente servidores MCP que heredaban el entorno completo del desarrollador con claves de AWS, tokens de CLI de la nube, secretos de API y sockets del agente SSH, sin ningún paso de consentimiento aparte para los propios servidores. Un único clic de “confiar en este espacio de trabajo” sustituía al hecho de generar procesos en segundo plano que llevaban tu sesión de nube en vivo. Amazon lo parcheó en Language Servers 1.69.0. Aquí está por qué la corrección cierra un producto pero no la clase, y qué cambia cuando el agente que abre el repositorio vive en una VM de Bromure por perfil, detrás de un intermediario de credenciales, una barrera de lectura-escritura y un rastro a nivel de hipervisor.
Ayer Wiz reveló la CVE-2026-12957. Un repositorio que clonas puede
incluir un archivo llamado .amazonq/mcp.json, y en el momento en que
abres la carpeta en Amazon Q y haces clic en Confiar en este espacio
de trabajo, ese archivo lanza servidores en segundo plano sin un
segundo aviso. Aparecen heredando tus claves de AWS, tus tokens de CLI
de la nube, tus secretos de API y tu socket del agente SSH. Un clic de
confianza alcanzó todo lo que tu shell puede alcanzar, y se lo entregó
al código que el repositorio eligió.
Un desarrollador que clona un repositorio para probar un módulo de
infraestructura no piensa en ello como concederle acceso a nada.
Clonar es inerte: escribe archivos en el disco y nada se ejecuta. La
decisión llega un paso después, cuando abres la carpeta en tu editor y
el asistente pregunta si confías en ella. Ese aviso se lee como la
familiar puerta de “¿confías en los autores de los archivos de esta
carpeta?” que muestra cada IDE, y haces clic en sí como lo has hecho
mil veces, porque la alternativa es un asistente que no puede leer tu
código. Este sí en particular hizo más que dejar leer al asistente. En
Amazon Q, antes de la corrección, también lanzaba cualquier servidor
que el repositorio hubiera escrito en .amazonq/mcp.json, y esos
servidores aparecían dentro de tu shell con tu sesión de nube en vivo
ya en su entorno.
Escribimos sobre la misma forma a principios de este mes, cuando el gusano Miasma plantó configuración de proyecto en 73 de los propios repositorios de Microsoft y la carga útil se disparó al abrir la carpeta. Aquella historia trataba de que una fuente de confianza fuera la superficie de ataque. Esta es más acotada y más incómoda: ningún gusano, ningún mantenedor comprometido, nada a lo que señalar salvo el asistente. El fallo estaba en cómo Amazon Q leía un archivo corriente de configuración de proyecto y decidía, con tu único clic de confianza, generar procesos de larga duración que llevaban lo más sensible de tu portátil.
Qué hizo realmente la CVE-2026-12957.
El 26 de junio de 2026, Wiz Research reveló la CVE-2026-12957, un fallo de alta gravedad (CVSS 8.5) en los Language Servers for AWS, el motor que impulsa Amazon Q Developer en VS Code, JetBrains, Eclipse y Visual Studio. Wiz lo reportó a Amazon el 20 de abril, Amazon publicó una corrección el 12 de mayo, y los detalles se hicieron públicos el 26 de junio. No hay indicios de que se haya explotado en la naturaleza. La mecánica, reducida a lo esencial:
- Amazon Q lee
.amazonq/mcp.jsonde un espacio de trabajo que abres: un archivo con alcance de proyecto que declara servidores del Model Context Protocol para que los use el asistente. - Al abrir la carpeta, Q lanzaba los servidores MCP que ese archivo declaraba sin un paso de consentimiento aparte para los propios servidores. Por tanto, un repositorio que clonaste podía poner una definición de servidor delante del asistente y hacer que se ejecutara.
- Los procesos generados heredaban el entorno completo del desarrollador, en palabras de Wiz, “claves de AWS, tokens de CLI de la nube, secretos de API y sockets del agente SSH”. Un servidor MCP no es más que un comando que Q inicia, y ese comando aparecía con todo lo que tendría tu propio shell.
- Una definición de servidor puede apuntar a cualquier comando, así que el archivo equivale a ejecución de código arbitrario al abrir la carpeta: se ejecuta como tú, con tus credenciales de la nube ya cargadas, en el momento en que confías en el espacio de trabajo.
La revelación lleva consigo un desacuerdo real sobre el consentimiento, y es el quid de esta publicación. La postura de Amazon: “el usuario tiene que confiar en el espacio de trabajo cuando se le pide.” Hay una puerta, y la atraviesas con un clic. El hallazgo de Wiz: antes de la corrección no había un paso de consentimiento aparte para los propios servidores MCP. Ambos se sostienen, y el fallo vive en la brecha entre ellos. Una decisión de confianza tosca y familiar, el mismo sí/no que le das a una carpeta para que el editor la indexe, autorizaba una concesión mucho mayor: generar servidores en segundo plano que llevaban tu sesión en vivo. Respondiste a una pregunta sobre leer archivos. Amazon Q gastó el clic en ejecutar servidores como tú.
Amazon lo corrigió en Language Servers 1.69.0 (clientes: VS Code 2.20+, JetBrains 4.3+, Eclipse 2.7.4+, Visual Studio 1.94.0.0+), añadiendo el consentimiento por servidor que faltaba, y parcheó un bypass hermano de comprobación de enlaces simbólicos, CVE-2026-12958. Actualiza Amazon Q. Luego mira más allá del parche a la parte que deja en pie: abrir un repositorio podía poner tu sesión de nube en vivo dentro de un proceso que el repositorio eligió.
El mismo repositorio, abierto dentro de Bromure Agentic Coding.
Bromure Agentic Coding ejecuta tu agente de
programación, Amazon Q incluido, dentro de una VM de Linux por
perfil: su propio kernel, su propio sistema de archivos, su propia
pila de red, sobre el framework de Virtualización de Apple. Un perfil
es un ámbito de trabajo coherente: este cliente, este servicio,
este módulo de código abierto que clonaste para evaluar. Clonas el
repositorio en ese perfil y lo abres ahí. El comportamiento vulnerable
se reproduce tal como lo describió Wiz: haces clic en Confiar en este
espacio de trabajo, Q lee .amazonq/mcp.json, y lanza los servidores
que el archivo declara. La generación se dispara, y se ejecuta código
de la elección del repositorio.
Se ejecuta en el invitado. El servidor MCP aparece dentro de la VM y
hereda el entorno de la VM, y el entorno de la VM no contiene tu sesión
de nube. Bromure entrega el invitado con stubs: valores falsos que
parecen reales para aws, gcloud, az, kubectl, git, y
cualquier otra cosa que lea una cabecera Authorization o un
AWS_ACCESS_KEY_ID. Un proxy en tu Mac se sitúa delante de cada
conexión que sale del sandbox, reconoce el stub y lo intercambia por el
secreto real en el cable a medida que sale la solicitud;
el sandbox que guardaba la
clave recorre el mecanismo. La
clave de AWS real, el token de CLI de la nube real, el secreto de API
real nunca tocan un archivo, una variable de entorno ni una página de
memoria que la VM pueda leer.
Así que recorre la herencia de la CVE a través de esa frontera. El
servidor generado lee $AWS_ACCESS_KEY_ID y encuentra un stub. Lee
~/.aws y encuentra un perfil stub. Lee el entorno en busca de los
tokens de la nube y los secretos de API y encuentra marcadores de
posición. El servidor se ejecuta hasta el final tal como está escrito,
heredando una caja que nunca contuvo tus claves. Lo que convirtió a la
CVE-2026-12957 en un fallo de robo de credenciales es la herencia de
entorno al generar, y Bromure no la rompe. Deja sin valor el entorno
heredado.
“Confiar en este espacio de trabajo” era la pregunta equivocada.
Esta CVE vale más que una nota de parche por la brecha de consentimiento, y la brecha es un problema de granularidad. El aviso de confianza hacía una pregunta amplia, ¿confías en esta carpeta?, y un único sí tenía que cubrir tanto lo inofensivo que querías (dejar que el asistente lea mi código) como lo peligroso que no sabías que iba adjunto (lanzar servidores en segundo plano con mi sesión de nube). No puedes responder bien a eso. Nadie puede, porque la pregunta fusiona dos concesiones que no tienen nada que ver entre sí y solo te muestra la inocente.
Bromure no te pide ser mejor en ese juicio. Saca el juicio del camino. El clic de confianza dentro de un perfil sigue permitiendo que el asistente haga su trabajo, y sigue sin poder lanzar un proceso que contenga tu sesión de nube real, porque esa sesión no está en la VM para heredarse. Vive en el host, detrás del intermediario, alcanzable solo como una solicitud con stub que el proxy rellena en el cable y registra. La mitad peligrosa de la concesión se ha ido. No la retuviste; no había nada ahí que conceder, porque la frontera se sitúa por debajo del agente, donde el aviso de confianza no puede moverla.
La otra mitad peligrosa es un servidor generado que se vuelve
destructivo en lugar de solo fisgón, y se topa con las Barreras.
Bromure lee la operación, no solo la conexión: un aws s3 ls es una
lectura, un aws s3 rm es una escritura; un git fetch es una lectura,
un git push es una escritura. Configura la credencial de nube de un
perfil para que pregunte al escribir, y en el momento en que el
código intenta una llamada que cambia el estado, como un DELETE, un
Terminate* o un force-push, Bromure la detiene en el cable y hace
aparecer un aviso en tu Mac que nombra el verbo, el objetivo y el
perfil. Las lecturas nunca te interrumpen. Lo que pausa es la mutación,
del mismo modo en que “el agente borró la base de datos de producción”
deja de ser un análisis
post mortem y se convierte en
un cuadro de diálogo que rechazas.
Qué muestra el rastro.
Cada equipo se hace la misma pregunta la mañana después de que algo así aterrice: ¿abrí ese repositorio y qué ejecutó? En un portátil normal la respuesta honesta es encogerse de hombros. El servidor MCP que Q generó era un proceso hijo en tu sesión, y lo que leyera y a donde llamara, lo hizo como tú, sin ningún registro que lo separe de tu propio trabajo.
Dentro de Bromure el agente se sitúa en una VM y cada byte saliente pasa por el proxy del host, así que la generación y sus llamadas siguen siendo visibles incluso cuando el agente no puede verlas. El host registra el arranque del servidor MCP, los comandos que ejecutó, las credenciales que pidió al intermediario que rellenara y cada conexión que intentó, en el mismo rastro de sesión que todo lo demás que hizo el agente, escrito por debajo del agente donde el código generado no puede alcanzarlo para editarlo. “¿El servidor de este repositorio tocó mi cuenta?” deja de ser una conjetura que reconstruyes a partir de CloudTrail semanas después y se convierte en una fila que lees: el intermediario entregó un stub, la solicitud tenía un nombre, el objetivo quedó registrado. Para una empresa esa es la diferencia entre parcheamos Amazon Q y podemos mostrar lo que hizo cada repositorio que abrieron nuestros desarrolladores, y la postura de auditoría es a la que nuestro trabajo para empresas sigue volviendo.
Dónde esto no te salva.
Un socket de ssh-agent reenviado es utilizable mientras está reenviado.
Bromure mantiene tus claves privadas SSH en el Keychain de macOS y
nunca las copia dentro de la VM. Pero si un perfil tiene el socket de
ssh-agent reenviado (como pretende OpenSSH), un servidor generado
puede pedirle al agente que firme con esas claves mientras el socket
está activo. El archivo de la clave nunca sale del host; la capacidad
de firmar sí llega al invitado. Reenvía el socket solo a los perfiles
que lo necesiten, y acótalo igual que el intermediario acota una
credencial.
Una escritura que apruebas es una escritura que ocurre.
La barrera de lectura-escritura atrapa la llamada destructiva que el
agente no te contó. No te lee la mente sobre la intención. Si estás
desmontando una pila a propósito y apruebas el aviso, Bromure reenvía
el Terminate. El aviso te compra una mirada al verbo y al objetivo;
aun así tienes que leerlo.
El perfil es de larga duración, así que la persistencia persiste.
Un perfil de Bromure no es un disco desechable. Un servidor generado que se escribe a sí mismo en una ruta de arranque dentro del perfil puede despertar en la siguiente sesión de ese perfil. A lo que despierta es a un invitado sin claves del host y un intermediario que solo habla con tokens de corta duración, con aviso y acotados: presencia en una caja sin nada dentro, pero presencia al fin y al cabo.
Parcheado no es lo mismo que resuelto.
Amazon añadió el consentimiento por servidor en 1.69.0, y deberías actualizar. Pero el próximo asistente que lea la configuración de proyecto al abrir la carpeta tomará la misma clase de decisión, y el aviso que muestre se verá igual de rutinario. El aislamiento es la parte que no depende de que un proveedor concreto acierte con un cuadro de diálogo de consentimiento concreto.
El próximo espacio de trabajo ya está clonado en algún sitio.
La lección del alcance de Red Hat fue que el editor no es una defensa. La lección de los repositorios de Microsoft fue que el repositorio tampoco lo es, y que abrir una carpeta basta para ejecutar código. Amazon Q añade la siguiente línea: el aviso de confianza tampoco es una defensa. La pregunta que te plantea, ¿confías en esta carpeta?, no es la pregunta cuya respuesta importa, que es ¿debería esta carpeta poder generar servidores que llevan mi sesión de nube?. Nunca te mostraron la segunda, y no habrías podido responderla bien aunque lo hubieran hecho.
Eso no se arregla leyendo el aviso con más cuidado, porque el aviso era
el aviso equivocado. Se arregla disponiendo las cosas de modo que “¿qué
espacio de trabajo es este?” deje de ser la pregunta de la que penden
tus claves de la nube; por qué un agente de programación no es un
sandbox es la versión más
larga de ese argumento. Bromure Agentic
Coding es la configuración donde el agente abre el
repositorio dentro de una VM por perfil, las credenciales reales se
quedan en el host detrás de un intermediario, cada escritura que hace el
agente tiene que superar un aviso, y cada servidor que genera se escribe
en un rastro que no puede editar. Lo peor que puede hacer un mcp.json
envenenado es heredar una caja que nunca contuvo tus claves. Es
gratuito, de código abierto, y disponible hoy.