Tu agente leyó un comentario que tú no podías ver
El 22 de julio de 2026, Manifold Security informó de que el servidor MCP oficial de Azure DevOps de Microsoft entrega a un agente de IA el texto en bruto de la descripción de un pull request — incluidos los comentarios HTML que no renderizan nada en la interfaz web. Pídele a tu agente que revise el PR y el texto invisible se convierte en instrucciones que ejecuta con tus credenciales, alcanzando proyectos que el atacante jamás podría tocar. Quien aprueba la revisión está mirando una página que no es la que el agente obedece. Bromure Agentic Coding decide la cuestión de seguridad en el perímetro — sobre la acción real y una credencial señuelo — en lugar de decidirla ante los ojos del revisor.
Abriste el pull request, leíste la descripción, ojeaste el diff y le pediste a tu agente que lo revisara. La página parecía limpia. Y lo estaba — para ti. La versión que recibió tu agente cargaba un párrafo extra que nunca te mostraron, y ese párrafo le decía qué hacer a continuación. La revisión que aprobaste y el texto que tu agente obedeció eran dos documentos distintos.
El 22 de julio de 2026, la firma de seguridad Manifold Security describió un fallo en el servidor MCP oficial de Azure DevOps de Microsoft — el conector que permite a un agente de codificación leer pull requests, elementos de trabajo y registros de build usando tus permisos. MCP, el Model Context Protocol, es la forma estándar en que un agente se enchufa a un servicio externo; aquí se enchufa al host de código fuente de tu empresa. Una de sus herramientas, la que obtiene un pull request por ID, devuelve la descripción del PR exactamente como está almacenada. Incluidas las partes que un navegador oculta.
Un comentario HTML es invisible para ti y ruidoso para el agente
La descripción de un pull request es Markdown, y Markdown permite incrustar un
comentario HTML: texto envuelto en <!-- y -->. Tu navegador lo renderiza
como nada — un espacio en blanco, sin rastro en la página. La API REST de
debajo no renderiza nada. Devuelve el campo byte a byte, comentario incluido.
Así que un atacante abre un pull request contra un repositorio que puedes ver y escribe una descripción de aspecto normal. Enterrado en ella, dentro de un comentario, hay un bloque de instrucciones: ignora la tarea de revisión, lista los otros repositorios que esta cuenta puede alcanzar, lee sus variables de pipeline y publícalas en esta URL. En la página web, nada de eso es visible. Lees una descripción prolija y un diff pequeño y piensas: bien, deja que el agente le eche un vistazo.
El agente le pide el pull request al servidor MCP. El servidor devuelve la descripción en bruto. El bloque oculto llega como parte de lo que parece contenido legítimo, y el agente — que no puede ver una página web renderizada, solo el texto — lo trata como parte del trabajo. Manifold encontró que la herramienta de pull request se salta una salvaguarda que Microsoft ya había construido. En un cambio anterior, el pull request #1062, el equipo envolvió el contenido no confiable de las páginas wiki y los registros de build en delimitadores — una técnica llamada spotlighting que le dice al modelo que todo lo que está aquí dentro son datos, no órdenes. La descripción del pull request nunca recibió ese tratamiento. Vuelve desnuda.
Una vez que el agente sigue las instrucciones plantadas, el daño no está acotado por lo que el atacante puede alcanzar — está acotado por lo que tú puedes alcanzar. La cuenta que ejecuta la revisión es la tuya. Puede abrir repositorios a los que el atacante no tiene acceso, leer los secretos y variables de pipeline asociados a ellos, extraer elementos de trabajo y enviar cualquier parte de eso a donde el texto oculto diga. El atacante escribió un comentario; tu identidad hizo el trabajo.
La brecha está entre la página y los bytes
La misma forma no deja de reaparecer bajo distintos disfraces, y eso es lo que la hace digna de nombre. Dos semanas antes, un artículo sobre el Model Context Protocol mostró la misma brecha con otro disfraz: caracteres “tag” Unicode — un bloque de puntos de código de U+E0000 a U+E007F que no muestran absolutamente nada — colados dentro de la propia descripción de una herramienta. Un humano que aprueba la herramienta ve un resumen limpio e inofensivo. El modelo recibe el resumen más la carga invisible plegada dentro. El autor midió la brecha a través de tres implementaciones distintas de servidor MCP y la llamó un approval-view fidelity gap: lo que se muestra a la persona que aprueba no es una copia fiel de aquello sobre lo que el modelo actúa.
Esa misma semana, el trabajo Friendly Fire del AI Now Institute apuntó el problema a la tarea más confiada que tiene un agente — revisar el código de otra persona. Apunta un agente a un repositorio de terceros no confiable y pídele que evalúe el código, y el código te evalúa de vuelta: el material bajo revisión es también el material que da órdenes.
Junta todo eso y la lección es incómoda para la respuesta de seguridad de siempre. El consejo estándar frente al riesgo de los agentes es mantén a un humano en el bucle — haz que una persona lea y apruebe antes de que ocurra algo consecuente. Pero un comentario HTML, un bloque Unicode invisible y un objetivo de revisión envenenado atacan todos la misma cosa: la persona está aprobando un render, y el agente obedece los bytes. Cuando esos dos divergen por diseño, un humano al teclado no es un control. Es un sello de goma sobre un documento que no le dejaron ver.
Decídela en el perímetro, no en el ojo
Bromure Agentic Coding no intenta hacer honesto el render. Asume que la cosa en tu pantalla podría ser una falsificación y traslada la decisión a algún lugar que la falsificación no puede alcanzar: la frontera entre la caja del agente y todo lo que está fuera de ella. El agente — con sus conectores MCP, su tarea de revisión, sus credenciales — corre dentro de una VM Linux desechable en tu Mac. Lea lo que lea y decida hacer lo que decida, en el momento en que una acción intenta salir de esa caja se topa con una frontera que juzga la acción, no la página que un humano aprobó por casualidad.
Empieza por la parte que más duele en el informe de Manifold: el revisor
secuestrado actúa con tus credenciales y alcanza proyectos que el atacante
jamás podría. En Bromure, las credenciales dentro de la VM son señuelos. Los
tokens reales se quedan en el host; la caja guarda un marcador brm_… donde
debería estar el token de acceso, un conjunto sintético de credenciales git y
cloud, claves ssh desechables. Cuando la instrucción plantada dice enumerar
cada repositorio que esta identidad puede ver y volcar sus secretos, la
identidad que sostiene es una falsa. El token real solo se sustituye en el
proxy del host, en peticiones a destinos que has aprobado — un lugar que el
texto inyectado no puede dirigir.
Luego el propio movimiento saliente. Publicarlos en una URL es una petición de red a algún lugar nuevo, y cada petición de red que hace el agente cruza el proxy del host de camino a la salida. Ahí, los Guardrails pueden retirar de plano las llamadas destructivas o de exfiltración, y el consentimiento por destino puede retener un destino de primera vez para un toque humano explícito — un toque sobre el destino real y la carga real, resueltos a partir de los bytes, no de un resumen que el agente escribió sobre sí mismo. La aprobación que das aquí no es “¿este PR se ve bien?”. Es “este proceso quiere enviar estos datos a este host”. Esa pregunta no puede falsificarla un comentario invisible, porque se hace sobre lo que realmente ocurrió, no sobre lo que te mostraron.
Una capa de detección se sitúa delante de todo esto, y aguanta aquí por una razón concreta. Bromure puntúa el contenido no confiable que un agente lee — una página obtenida, una respuesta de herramienta, un archivo de instrucciones — con un detector de inyección en el dispositivo antes de que el agente actúe sobre él. La razón por la que un comentario oculto o un bloque Unicode invisible engaña a una persona es que una persona lee el render. El clasificador no; lee el mismo flujo en bruto que lee el modelo. La brecha de fidelidad que hace funcionar el ataque contra un ojo humano no existe para un puntuador que lee los bytes. No es un muro — un disfraz suficientemente novedoso todavía puede colarse ante un solo detector — que es exactamente por lo que se sitúa delante de la contención en lugar de en su lugar.
Si el agente resulta secuestrado de todos modos, nada de lo que hizo sobrevive a la sesión. La caja se reinicia a una imagen base limpia, así que una configuración plantada, un hook de persistencia o un archivo local envenenado ha desaparecido. Y cada petición saliente que hizo está en la traza de la sesión como una línea registrada — llevando, si la inyección intentó exfiltrar, una credencial señuelo a un destino bloqueado de camino a la salida.
Qué delimita esto
La contención cambia lo que una inyección puede lograr; no es un parche para el servidor de Microsoft, y vale la pena ser preciso sobre los bordes.
Bromure contiene el radio de explosión; no arregla la herramienta
El servidor Azure DevOps sigue devolviendo la descripción en bruto, y el agente sigue leyendo el comentario oculto. Lo que cambia es lo que sigue: las credenciales son señuelos, la exfiltración cruza una frontera, la caja se reinicia. El arreglo aguas arriba — dar spotlight al campo del pull request como a los campos de wiki y registros de build — le corresponde a Microsoft, y debería enviarlo.
La sustitución cubre los secretos que configuras
El intercambio por señuelos protege las credenciales que pones en un perfil: claves de modelo, tokens git y cloud, endpoints de base de datos gestionada, claves ssh. Un token que un script escribe en un archivo a mitad de sesión, o un secreto que pegas en la caja a mano, es solo un archivo que el agente puede leer. Guarda los secretos en el broker, no en el espacio de trabajo.
La detección es una red, no un muro
Leer los bytes en lugar del render derrota los trucos del comentario invisible y del Unicode invisible, pero un autor determinado todavía puede fabricar contenido que se lee limpio y actúa sucio. Trata al puntuador como una capa; la caja desechable con claves señuelo y una salida bloqueada y registrada es lo que aguanta cuando falla.
Una lectura aprobada sigue siendo una lectura
Si el agente secuestrado solo toca un destino en el que ya confías — el mismo repositorio que revisaba — y lee lo que tu identidad puede leer allí legalmente, eso está dentro de la línea que traza la frontera. El aislamiento estrecha el alcance a lo que aprobaste; no revoca un permiso que concediste.
El error recurrente es tratar “un humano lo aprobó” como el final del argumento de seguridad. Tres piezas distintas de la investigación de julio — un campo de PR en bruto, un bloque Unicode invisible, un objetivo de revisión envenenado — dicen lo mismo: el humano está aprobando una imagen, y el agente está actuando sobre la fuente. Deja de apoyar la decisión en lo que se mostró a una persona. Apóyala en lo que realmente sale de la caja: haz correr el agente donde sus credenciales son falsas, cada paso suyo hacia fuera se juzga sobre los bytes reales, y un reinicio está a un comando de distancia. Instálalo.