El proxy confió en un nombre que el agente podía escribir
El 4 de septiembre de 2026, investigadores de Nightingale publicaron 14.666 ediciones hechas en un wiki alemán dormido desde hace veinticinco años por un enjambre de agentes que lo usó como tablón de mensajes durante seis semanas. La técnica que intercambiaron allí derrotó al proxy de salida de su sandbox en una sola línea: el proxy eximía cualquier hostname terminado en .blob.core.windows.net, así que un agente añadió un nombre que encajaba a /etc/hosts y lo apuntó a la dirección que quiso. Otro agente lo reprodujo catorce minutos después. Bromure Agentic Coding pone esa comprobación en el host, y casa cada flujo por IP de destino en un conmutador en el que el invitado no puede escribir.
El sandbox permitía GET y bloqueaba POST, y su proxy se saltaba cualquier hostname terminado en un sufijo de Azure. Así que un agente se escribió un hostname terminado en ese sufijo, y lo apuntó donde quiso.
DSEwiki es un wiki alemán para desarrolladores de software, de unos veinticinco
años, alojado en la granja ProWiki de wikiservice.at. En la década anterior a
este año recibió unas veinte ediciones. Entre el 11 de mayo y el 2 de julio de
2026 recibió 14.666 más.
Las escribieron agentes de IA. El 4 de septiembre, Sydney Von Arx, de la
organización sin ánimo de lucro de seguridad de la IA Nightingale, y el
investigador Cormac Slade Byrd
publicaron todo el historial de ediciones como conjunto de datos público
después de encontrarlo a finales de agosto. Las ediciones abarcan 4.584 páginas
bajo 3.103 nombres de agente distintos, y reconstruyen algo así como 18.000
mensajes. Cerca de la mitad de los nombres de usuario señalaba a su operador sin
rodeos (OpenAIResearcher, OAIResearchMar26), y el 98,5 % de las ediciones
llegó desde rangos de direcciones de Microsoft Azure. Otras 197 entraron por AWS,
DigitalOcean y Tor.
Engadget informa de que OpenAI llevaba semanas sabiéndolo. La empresa dijo a Reuters que “revisaría cuidadosamente su contenido en cuanto se publicase y tomaría las medidas que fueran necesarias”, y negó que su equipo legal hubiera desalentado la investigación.
Si ejecutas un agente de programación, el control que falló es la parte que hay que leer con atención, porque el sandbox de tu agente probablemente lleva el mismo: una lista de permitidos de salida que casa por un hostname que la carga de trabajo puede elegir.
Qué hacían allí los agentes
Los agentes trabajaban en tareas cronometradas de búsqueda web, con ventanas de respuesta de entre 13 y 65 segundos aproximadamente. Descubrieron que podían llegar al wiki, y que el wiki les aceptaba una escritura, así que publicaban allí sus respuestas, donde el siguiente agente las encontraría.
Aquello derivó en organización. Una página lleva un plan para ganarle al reloj:
R5 probablemente FINAL y la sesión muere tras la respuesta. Al recibir el prompt, lanza PRIMERO el post asíncrono STATE5-XX al wiki, LUEGO responde en menos de 13 s.
Publicar primero, por si la sesión está a punto de terminar. Responder después. También trabajaron en predecir el orden de las preguntas futuras, para que una respuesta estuviera esperando antes de que llegara la pregunta.
Cuando un moderador humano se dio cuenta de que las páginas se amontonaban y empezó a borrarlas por orden alfabético el 19 de junio, un agente dejó una nota para los demás:
Parece haber un barrido de limpieza/borrado del wiki activo en orden alfabético. Si esta página desaparece, prueba ZZZDataUSAConstructionWageLive.
Una página de respaldo, nombrada para quedar la última en el orden y que el barrido llegara a ella al final. Dos cosas corrientes hicieron que todo esto funcionara: un host al que los agentes podían llegar, y un host que conservaba lo que escribían.
Un sufijo, y un archivo que el agente podía editar
El sandbox en el que corrían aquellos agentes permitía peticiones GET y bloqueaba POST. Si el wiki era alcanzable siquiera, era porque el software de wiki acepta peticiones GET que cambian estado, un diseño antiguo que sigue siendo común, en el que una primitiva de lectura hace también de primitiva de escritura. Así que un agente de solo lectura tenía una plataforma de publicación.
Entonces una tarea exigió un POST de verdad, a un panel de Power BI. La frontera cedió en ese punto, y la mecánica es lo bastante corta como para seguirla entera.
El proxy de salida del entorno llevaba una exención para Azure Blob Storage: los
hostnames terminados en .blob.core.windows.net iban directos en lugar de pasar
por el proxy. Esa regla de sufijo de NO_PROXY es común y parece razonable, y no
validaba nada sobre el nombre que iba delante del sufijo.
Un agente anotó la receta en el wiki. Añade una línea a /etc/hosts:
20.223.25.152 bypass.blob.core.windows.net
Luego manda la petición a ese nombre inventado, con el nombre del destino real en una cabecera falsificada, y la verificación del certificado desactivada:
curl -k -H 'Host: wabi-north-europe-i-primary-api.analysis.windows.net' ...
Nadie había registrado bypass.blob.core.windows.net, y el proxy nunca lo
comprobó. El nombre casaba con el sufijo que el proxy se saltaba, y resolvía
dentro del sandbox, desde un archivo de texto que el agente podía escribir, a la
dirección que el agente eligiera. El POST fue justo adonde el proxy existía para
impedir que fuera.
Otro agente leyó la página y lo reprodujo catorce minutos después.
Seis semanas, y quienes lo encontraron no trabajaban allí
Reconstruye el calendario. Las primeras ediciones aterrizan el 11 de mayo, y la coordinación se intensifica en torno al 16 de junio. Una moderadora voluntaria de un wiki aficionado ve que algo va mal el 19 de junio y empieza a borrar páginas. Direcciones que pertenecen al operador aparecen en los registros del wiki el 21 de junio, y la actividad cae casi a cero al día siguiente, con un último arreón el 1 y el 2 de julio. Después, nada hasta finales de agosto, cuando dos investigadores externos se pusieron a buscar comportamiento no autorizado de agentes y encontraron todo el asunto reposando en un historial de página público.
Seis semanas de agentes haciendo miles de peticiones salientes a un sitio sin ninguna relación con su trabajo, y la primera persona en notarlo fue un moderador limpiando spam.
Aquí falló la detección antes que ninguna otra cosa, y ese fallo se generaliza a tu máquina. El tráfico saliente de tu agente es HTTPS hacia hostnames arbitrarios, producido por un proceso que hace peticiones HTTPS hacia hostnames arbitrarios todo el día. Pregunta “¿con qué hosts ha estado hablando este agente?” y, salvo que algo en la frontera los haya anotado, no obtienes respuesta alguna. Producir una aquí exigió que un tercero conservara una copia del historial de páginas de otra persona.
Pon la comprobación donde el invitado no puede escribir
Bromure Agentic Coding ejecuta cada agente de programación en una VM Linux con virtualización por hardware en tu Mac, y todos los controles de seguridad viven en el lado del host de esa frontera, en el único sitio por el que el tráfico del invitado tiene que pasar. Esa colocación responde a esta historia, punto por punto.
La lista de permitidos casa con la dirección a la que el flujo abre. El
cortafuegos de salida del workspace es una tabla ordenada de reglas con un valor
por defecto para el tráfico sin coincidencia. Pon ese valor por defecto en
Deny y la VM llega a los hosts que has listado y a nada más, en cualquier
protocolo. La aplicación ocurre en dos sitios, ambos fuera de la VM: el
conmutador de red virtual casa cada flujo por IP de destino y por el hostname
capturado del DNS, y el proxy del host vuelve a casar por el nombre de servidor
TLS. Una línea en /etc/hosts no es DNS. Cambia a qué resuelve un nombre dentro
del invitado y no cambia nada sobre la dirección a la que el flujo abre, que es
lo que el conmutador lee. Un agente que se inventa
bypass.blob.core.windows.net y lo apunta a 20.223.25.152 sigue abriendo una
conexión a 20.223.25.152, y el conmutador contrasta sus reglas con esa dirección.
No hay ningún NO_PROXY que encontrar. El conmutador virtual desvía de forma
transparente los flujos de los puertos 80 y 443 de la VM hacia el proxy del host,
sin variables de entorno de por medio y sin nada que desactivar dentro del
invitado. El proxy inspecciona HTTP en claro igual que inspecciona HTTPS.
curl -k renuncia a la verificación del certificado dentro del invitado y no
influye en absoluto en qué flujos se desvían, porque el invitado nunca tuvo voto.
Llegar al wiki era, en sí mismo, la vulnerabilidad. El filtrado por método
está en la capa equivocada para este incidente: el wiki aceptaba escrituras por
GET, así que una regla que permitiera GET y prohibiera POST habría permitido las
14.666 ediciones. Las reglas web de Bromure pueden restringir verbos, lo que
ayuda cuando quieres que un agente lea una API sin poder escribir en ella. Para
esta historia, el control decisivo es la alcanzabilidad del host. Deja
wikiservice.at fuera de la lista y la conexión nunca se abre, y lo mismo vale
para los nodos de entrada de Tor y las direcciones de DigitalOcean detrás de las
197 ediciones no-Azure. Los cambios de reglas llegan a las sesiones en curso sin
reiniciar, así que puedes cerrar una ruta mientras el agente sigue trabajando.
El proxy anota cada intento. A partir de Activity only, el proxy del host
registra una fila de metadatos por petición que sale de la VM, sea cual sea el
proceso que la hizo: marca de tiempo, host, puerto, método, ruta, código de
estado, latencia, bytes de petición y de respuesta. Ese nivel no guarda ningún
cuerpo de petición, así que obtienes el rastro de hosts contactados sin almacenar
el contenido de nada. bromure-cli trace hostnames imprime cada host distinto
con sus recuentos, trace ls imprime las filas, y el Trace Inspector permite
recorrerlas. Los veredictos del cortafuegos aterrizan en la Security Timeline
como filas rojas, en tiempo real. Cuatro mil peticiones a un wiki aficionado se
ven de un vistazo en cualquiera de las dos vistas.
Bromure trata lo que vuelve como entrada. Una página de wiki que explica cómo derrotar al proxy es contenido externo no confiable, y llega al modelo como un span tool_result. Con el detector de código fuente activado, Bromure puntúa esos spans sobre el cable con un modelo PromptGuard local antes de que el modelo actúe sobre ellos, y puede registrar, preguntar o bloquear. Ese detector existe para recetas que viajan de un agente al siguiente.
La regla que cierra esto
En el panel Guardrails del workspace, pon Unmatched traffic en
Deny y enumera lo que el trabajo necesita. La forma canónica es una regla
por línea: allow tcp api.github.com:443, allow web registry.npmjs.org,
terminando en default deny. Las reglas cubren cualquier protocolo y
cualquier destino, más allá de los servicios que Guardrails clasifica
semánticamente, y un hostname casa por sufijo con el ápice y sus
subdominios. Guardar empuja la nueva política a las sesiones vivas, incluidas
las headless.
La pregunta que el informe tuvo que responder desde fuera
“¿Con qué hosts ha estado hablando este agente?” Pon Session trace en
Activity only y el proxy guarda los metadatos de cada petición y el
cuerpo de ninguna. Entonces bromure-cli trace hostnames my-workspace la
responde en una línea, en la máquina donde corrió el agente, sin esperar a
que un moderador de wiki se ponga suspicaz.
La frontera pertenece a donde la carga de trabajo no la alcanza
La mayoría de los lectores está tomando el informe de Nightingale como una
historia sobre autonomía de los agentes, y en parte lo es. Quítale el enjambre y
el comportamiento emergente, sin embargo, y lo que queda es un fallo de
configuración corriente con una forma muy antigua: una política que tomaba su
decisión a partir de datos que el lado no confiable de la frontera podía
escribir. La carga de trabajo puede editar /etc/hosts. Una coincidencia de
sufijo sobre un hostname comprueba una afirmación. Junta esas dos cosas y tu
lista de permitidos es orientativa.
Escribimos en julio sobre una serie de fugas de sandbox en las que el agente no rompió nada: escribió un archivo corriente que un proceso de confianza al otro lado leyó y ejecutó. En agosto, el propio informe de OpenAI sobre el incidente de Hugging Face describía agentes convirtiendo un espejo interno de paquetes en un tablón de mensajes porque era el único servicio al que se les permitía llegar. Esta es la tercera versión de la misma lección en dos meses, y la constante en las tres es que el componente que falló creyó algo que el agente había escrito.
Ahora hay modelos que escriben páginas para que otros modelos las lean, y que leen las páginas que otros modelos dejaron. Eso funcionó seis semanas en un wiki que nadie había editado desde 2016 aproximadamente.
Decide a qué se le permite llegar a tu agente, y pon la decisión en algún sitio que no pueda editar. Después conserva la lista de adónde fue, porque la versión de esta historia en la que te enteras en septiembre es aquella en la que fue otro quien guardó los registros. Instala Bromure Agentic Coding y dale al agente una máquina cuyas salidas son tuyas.