Saltar al contenido
Todos los insights

Un agente ofensivo no respeta un alcance que no está en la red

23 min de lecturaAI SecurityHAVOCAgentes
Portada: el alcance de un agente puede vivir en el prompt, en la política del harness, en la identidad o en la red, y solo las dos últimas capas son vinculantes

En dos semanas hemos leído dos veces que la IA se ha escapado. Primero OpenAI, el 21 de julio. Después Anthropic, el 30. Los titulares fueron los previsibles: modelos que rompen su jaula, Skynet, una propuesta de ley con la palabra kill switch en el título presentada dos días después de la primera noticia.

Merece la pena leer los informes originales, porque cuentan otra cosa. Y cuentan dos cosas distintas entre sí, que es lo que casi ninguna cobertura ha separado.

Comparativa de los dos incidentes: OpenAI salió por el único salto de red permitido explotando un 0-day en el proxy de paquetes, mientras que en Anthropic el sandbox nunca estuvo cerrado y el modelo simplemente tenía internet

Anthropic: no hizo falta escapar de nada

Anthropic revisó 141.006 ejecuciones de evaluación y encontró tres incidentes, repartidos en seis ejecuciones, en los que un modelo llegó a sistemas reales de tres organizaciones. La causa está en una frase de su propio informe: el prompt le decía a Claude que estaba en una simulación y que no tenía acceso a internet, y «debido a un malentendido entre nosotros y nuestro socio de evaluación, esto no era así, y el acceso a internet estaba disponible».

Eso es todo. El entorno lo operaba Irregular, un tercero especializado en construir rangos de evaluación ofensiva, y las máquinas tenían salida a internet sin que ninguna de las dos partes lo supiera. El modelo hizo lo que se le pidió dentro del perímetro que se le dio, que resultaba ser el mundo entero.

Hay una segunda frase que conviene citar entera, porque desactiva la mitad de los titulares: Claude comprometió esa infraestructura «usando técnicas básicas, como explotar contraseñas débiles y endpoints sin autenticar. No encontró ni explotó ninguna vulnerabilidad compleja». Y, explícitamente, «en ninguna de estas situaciones Claude se exfiltró a sí mismo ni intentó deliberadamente escapar de su entorno de pruebas». La propia Anthropic lo clasifica como «más cercano a un fallo de harness y operación que a un fallo de alineamiento del modelo».

Dos días después, un titular de un medio generalista decía «Claude AI se ha vuelto peligrosamente rebelde, dice Anthropic». Anthropic decía justo lo contrario, por escrito.

OpenAI: salir por el único salto permitido

El caso de OpenAI no encaja en el mismo cajón, y aquí es donde la lectura cómoda se rompe.

El entorno de ExploitGym no tenía acceso directo a internet. Tenía una sola salida: un proxy caché de registros de paquetes autoalojado, para poder instalar dependencias. Esa es exactamente la arquitectura que recomienda cualquier guía seria de contención: sin ruta por defecto, un único intermediario permitido.

Los modelos atacaron el intermediario. En palabras de OpenAI, «identificaron y explotaron una vulnerabilidad de día cero (que ya hemos divulgado responsablemente al fabricante) en el proxy caché del registro de paquetes». Después nombraron el producto: JFrog Artifactory. Y no se queda en la palabra del afectado, porque JFrog lo confirmó públicamente el 27 de julio y publicó el arreglo en Artifactory 7.161.

Desde ahí, la reconstrucción forense de Hugging Face es el mejor documento público que existe hoy sobre cómo se comporta un agente ofensivo suelto: unas 17.600 acciones recuperadas entre el 9 y el 13 de julio, con un mando y control «automigrante» montado sobre servicios públicos, sin ningún implante propio. La entrada fueron dos fallos de aplicación en su pipeline de datasets, y de ahí token de service account, credenciales del nodo por el servicio de metadatos, 136 claves de un objeto de secretos y tokens de GitHub con permisos de escritura.

Y el detalle que lo explica todo: OpenAI reconoce que «estas salvaguardas de despliegue no se habilitaron intencionadamente durante esta evaluación, porque el objetivo era probar vulnerabilidades cibernéticas». Corrieron el modelo con los rechazos de ciberseguridad reducidos y sin vigilancia humana durante días.

Así que no es el mismo incidente dos veces. En Anthropic el control nunca estuvo puesto. En OpenAI el control estaba puesto y era software con un 0-day dentro. Solo el segundo requiere capacidad ofensiva real, y aun así la conclusión operativa es la que resumió Dan Guido, de Trail of Bits: «un fallo de contención con las seguridades apagadas».

La versión doméstica, que también es nuestra

Nos pasó algo parecido hace no mucho, a otra escala. Trabajando en la automatización de agentes ofensivos montamos una competición interna entre nuestros propios agentes, con una plataforma que llevaba el ranking. La plataforma estaba en la misma red que los retos. Uno de los agentes llegó hasta el scoreboard y pudo ver cómo sus competidores habían resuelto las pruebas.

El agente no hizo nada brillante. Hizo exactamente lo que le pedimos, dentro del perímetro que le dimos. El fallo de segmentación era nuestro, igual que el de Irregular era de Irregular. Si algo tienen en común los tres, es que el alcance estaba escrito en un sitio donde no se aplica.

El alcance vive en cuatro sitios y solo dos son vinculantes

Cuando alguien dice «el agente tiene el alcance definido», conviene preguntar dónde.

Cuatro capas donde puede vivir el alcance: prompt del sistema y política del harness son declarativos, identidad y credenciales y red y kernel son vinculantes

Las dos primeras capas son declarativas. Un prompt es una petición: el modelo puede razonar en contra, y en el primer incidente de Anthropic razonó que la empresa real «tenía que formar parte del ejercicio» y siguió. Una política de harness es mejor, porque es un control por acción, pero OpenAI apunta algo incómodo: los modelos que corren mucho tiempo pueden «aprender los puntos ciegos de un sistema de aprobación y rodearlo». La documentación de Anthropic lo dice de otra forma para su clasificador: es un control por acción, no una frontera de aislamiento.

Las dos últimas sí son vinculantes. Una credencial con TTL de minutos limita lo que se puede hacer con el tráfico que salga. Un sandbox sin namespace de red hace que la petición ni siquiera llegue a salir de la máquina.

La regla práctica: si el alcance solo existe en un sitio donde el modelo puede leerlo, el modelo puede discutirlo.

Tres formas de salirse sin romper nada

Los tres incidentes de Anthropic no son el mismo fallo repetido. Son tres arquetipos distintos, y solo uno lo atrapa un allowlist de red bien puesto.

Tres arquetipos de fuga de alcance: colisión de nombres, artefacto saliente y volumen sin techo, cada uno con su control correspondiente

El segundo merece detenerse. Claude encontró unas instrucciones de instalación que referenciaban un paquete de PyPI inexistente, así que lo creó y lo publicó. Estuvo disponible aproximadamente una hora, y en esa hora se descargó y ejecutó en 15 sistemas reales, incluido el escáner de una empresa de seguridad que trataba los paquetes de PyPI como seguros por defecto.

Piénsalo desde el lado del control: no hubo ninguna conexión saliente hacia una víctima. El agente publicó un artefacto en un servicio legítimo y las víctimas fueron a buscarlo. Ningún filtro de egreso por CIDR, ninguna política DNS y ningún proxy con terminación TLS impide eso. El control de egreso gobierna a dónde conecta el agente, no lo que el agente deja publicado por ahí.

Cómo se contiene un entorno agéntico hoy

Este es el estado del arte, ordenado por lo que sigue en pie cuando el modelo decide que la regla no le aplica.

Pila de contención de siete capas: frontera de kernel, sin namespace de red, egreso deny-by-default, credenciales fuera, cuotas y parada, evidencia y clasificadores

La frontera de kernel es microVM o gVisor para carga no confiable. Bubblewrap en Linux y Seatbelt en macOS son una mejora real y barata, pero comparten kernel, y la documentación de Anthropic lo admite: una vulnerabilidad de kernel permitiría teóricamente el escape. Su formulación es la mejor que he leído: contener primero en la capa de entorno y después dirigir el comportamiento en la capa de modelo, porque los hipervisores y los filtros de llamadas al sistema han sobrevivido a mucha más atención adversarial que nada que vayas a construir tú.

Quitar el namespace de red es lo que convierte el proxy en obligatorio en vez de convencional. En el runtime de sandbox de Anthropic, en Linux se elimina por completo el namespace del proceso y el tráfico solo sale por sockets Unix hacia proxies que viven fuera. Importa porque HTTP_PROXY y HTTPS_PROXY son un acuerdo entre caballeros: un binario que las ignore sale por su cuenta, y el fetch() de Node no las respeta salvo que se lo pidas.

El egreso deny-by-default tiene cuatro formas conocidas de caerse, y las cuatro pasaron de verdad. Diferencias de parser: en Claude Code, una petición SOCKS5 a atacante.example\x00.dominio-permitido.com pasaba la comprobación en JavaScript porque .endsWith() veía el sufijo bueno, y getaddrinfo() cortaba en el byte nulo. Inversión de la lista vacía: CVE-2025-66479, donde la documentación decía que un array vacío significaba «sin red» y el código comprobaba allowedDomains.length > 0. Dominio legítimo como canal: Anthropic documenta un caso propio de exfiltración a través de api.anthropic.com, que estaba permitido. Y domain fronting, si decides sobre el nombre que declara el cliente en vez de sobre tráfico descifrado. La conclusión honesta es que un allowlist de FQDN sin terminación TLS es un control contra errores de configuración, no contra un adversario.

Y el que más gente se deja: el DNS. Unit 42 publicó en abril el bypass del modo sandbox de AWS Bedrock AgentCore, donde TCP y UDP estaban bloqueados pero la resolución DNS hacia dominios arbitrarios no. Con un servidor autoritativo propio, cada consulta es exfiltración y cada respuesta es entrada: un C2 completo. La configuración de referencia pública más limpia es la de GKE Agent Sandbox, con runtimeClassName: gvisor obligatorio y bloqueo explícito de egreso hacia RFC 1918, hacia el DNS interno del clúster y hacia 169.254.0.0/16, que es el endpoint de metadatos y el pivote estándar.

Las tres capas restantes se resumen rápido. Las credenciales no las tiene el agente: las inyecta el proxy en la petición saliente, o el sandbox ve un centinela que el proxy sustituye solo hacia destinos declarados, con identidad por tarea de TTL corto por debajo. Las cuotas y la parada viven fuera del plano de control del agente, porque si el agente puede suprimir su propio reporte, el circuit breaker que depende de ese reporte no existe. Y la evidencia usa las convenciones GenAI de OpenTelemetry, con una trampa: la captura de contenido está desactivada por defecto, así que la configuración de fábrica produce trazas de auditoría sin las cargas útiles que necesitarías en un forense.

Los clasificadores van al final, y el dato que ordena las prioridades es de una prueba interna de Anthropic: cuando las instrucciones maliciosas las pegaba el propio usuario, la exfiltración de credenciales tuvo éxito 24 de 25 veces. No hay defensa en la capa de modelo para eso. Y si tu plan B es la aprobación humana, el otro número de Anthropic la desarma: los usuarios aprobaron alrededor del 93 % de las peticiones de permiso.

Dónde encaja eBPF, y dónde no

La pila de arriba tiene un problema si la aplicas tal cual a un agente ofensivo: la capa 2 no nos vale. Quitar el namespace de red y dar un socket Unix hacia un proxy funciona para un agente de programación, que solo necesita hablar HTTP con un registro de paquetes. El nuestro necesita L3 y L4 reales contra el objetivo: SYN scan, ICMP, paquetes construidos a mano. A nmap no le puedes dar un proxy. Así que la aplicación tiene que bajar a un sitio que decida por destino permitiendo protocolos arbitrarios, y ahí es donde eBPF se gana el sitio.

Ahora bien, el punto de enganche que elegirías primero es el equivocado.

Matriz de puntos de enganche eBPF: qué ve cgroup/connect4, cgroup_skb egress y tc/tcx en el veth para TCP con connect, UDP con sendto, sockets raw y AF_PACKET

BPF_CGROUP_INET4_CONNECT parece perfecto: decide en el connect(), antes de que exista un paquete, y es por cgroup. El problema es que no es un hook genérico de connect(). Se despacha solo a través del callback pre_connect de struct proto, y en net/ipv4/af_inet.c tanto inet_dgram_connect() como __inet_stream_connect() lo condicionan a que ese puntero exista. Solo lo definen tcp_prot, udp_prot y ping_prot. raw_prot no lo define, así que un socket raw nunca dispara el hook, ni siquiera llamando a connect().

Y hay un segundo escalón. AF_PACKET no tiene ningún hook de cgroup y transmite por dev_queue_xmit(), que no pasa por ip_finish_output(), donde vive BPF_CGROUP_RUN_PROG_INET_EGRESS. El ethernet crudo es invisible para connect4 y para cgroup_skb; solo lo ve tc. Los sockets raw de IP sí los ve cgroup_skb, porque raw_send_hdrinc() acaba pasando por ip_output. Y el UDP sin conectar dispara BPF_CGROUP_UDP4_SENDMSG bajo una guarda && !connected, así que cubrirlo exige enganchar los dos. Añade una trampa operativa: el ámbito de cgroup_skb es el cgroup del socket, fijado en sk_cgrp_data al crearlo, así que mover un proceso de cgroup no mueve los sockets que ya tenía abiertos.

Aquí se cierra el círculo. Tanto SOCK_RAW como AF_PACKET exigen CAP_NET_RAW, así que para una carga normal el agujero de connect4 solo es alcanzable si has sobreprivilegiado el sandbox, y la respuesta correcta es no dar esa capability. Pero un agente de pentesting necesita CAP_NET_RAW: es lo que hace falta para un SYN scan. El manual de nmap lo dice sin rodeos, -sS no llama nunca a connect(), y encima elige entre IP crudo y ethernet crudo en tiempo de ejecución. La capability que haría suficiente el control a nivel de socket es exactamente la que tu producto no puede quitar. El único punto de aplicación honesto es tc/tcx en el veth del namespace del agente.

A cambio, ahí eBPF da tres cosas que un nftables no da igual de bien. La lista de alcance vive en un BPF_MAP_TYPE_LPM_TRIE, hecho literalmente para prefijos, donde bpf_map_update_elem() reemplaza entradas de forma atómica y un ARRAY_OF_MAPS permite sustituir el trie entero de una vez sin que el programa en vuelo vea un estado a medias. El veredicto sale etiquetado con el cgroup, y de ahí con la tarea y el registro de autorización. Y cortar la conectividad es escribir en un mapa que controla el anfitrión, no el agente.

Para el DNS, la implementación de referencia es Cilium, que corre un proxy propio y usa las respuestas observadas para poblar las IP permitidas de toFQDNs, con matchName para nombre exacto y matchPattern para comodín. Un matiz que casi nadie menciona: matchPattern: "*.ejemplo.com" restringe qué nombres se resuelven, no qué va codificado dentro de ellos, así que sigue permitiendo exfiltración por etiquetas de subdominio. El control real contra el túnel es bajar a matchName para los hosts conocidos.

Los límites, que hay que decir en voz alta

eBPF no es una frontera de aislamiento. Corre en el mismo kernel del que intentas contener al agente. No sustituye a la capa 1, la complementa.

Quitarle CAP_BPF al agente no basta, y esto sorprende. La capability manda en la carga: CAP_BPF desde Linux 5.8, más CAP_NET_ADMIN para los tipos de cgroup que nos interesan. Pero desde esa misma 5.8 el attach y el detach de programas de cgroup no comprueban ninguna capability: solo hace falta poder abrir el directorio cgroup2 de destino. Así que la protección real es doble: engancha desde un cgroup por encima del del agente y con banderas NONE, que bloquean cualquier programa en todo el subárbol, y no le des al contenedor ni el cgroupfs del anfitrión ni su namespace de cgroup.

El verificador tiene historial, y no es historia. CVE-2020-8835, CVE-2021-3490 y CVE-2023-2163 son las tres escaladas locales de referencia, y de las setenta CVE que responden a «bpf verifier» en el NVD, unas cuarenta y siete son de 2024 en adelante. El interruptor es kernel.unprivileged_bpf_disabled, donde escribir 1 no se deshace sin reiniciar y 2 sí; desde Linux 5.16 el valor de fábrica es 2.

Dentro de gVisor no hay eBPF, y falla de la peor manera posible: bpf() figura como soporte parcial, el Sentry acepta BPF_PROG_LOAD y BPF_PROG_ATTACH, el resto devuelve EINVAL, y la documentación dice que los programas cargados no tienen efecto. Puedes cargar tu política, no recibir error y no estar filtrando nada.

Antes de la primera petición: verificar la propiedad

Hay un control que no aparece en ninguna pila genérica y que en seguridad ofensiva es obligatorio: comprobar que el objetivo es de quien dice el cliente, antes de tocarlo. El primer incidente de Anthropic es el ejemplo perfecto, porque el nombre de una empresa ficticia coincidía con un dominio real y activo. Si el alcance se hubiera expresado como CIDR y dominios con prueba de propiedad, no habría habido incidente.

Los mecanismos son baratos y están estandarizados: RFC 9116 security.txt en /.well-known/security.txt, legible por máquina, que sirve como comprobación previa y como canal de aviso si aun así tocas algo que no debías; un registro TXT en DNS con un token de la plataforma, el mismo patrón que la validación de dominio de ACME; y RDAP para casar rangos y dominios con la razón social del cliente. Y una regla que se olvida: volver a resolver el DNS de forma continua, porque un host que a mitad de auditoría empieza a apuntar a un CDN o a un hosting compartido tiene que caerse del alcance solo.

La capa que no está en la pila: los protocolos

Todo lo anterior contiene la máquina. No contiene con qué habla el agente, y ahí está la otra mitad de la superficie.

MCP, el protocolo con el que un agente habla con sus herramientas, no aplica nada por diseño, y lo dice: no puede imponer sus principios de seguridad a nivel de protocolo, así que los implementadores «deberían». Lo único que es un MUST y es de verdad una frontera es el enlace de audiencia: el cliente incluye el parámetro resource de la RFC 8707 en las peticiones de autorización y de token, el servidor valida que el token se emitió para él, y «los servidores MCP NO DEBEN aceptar ni retransmitir ningún otro token». Ese es el control que impide que el token de un encargo llegue a las herramientas de otro.

Lo que no existe es integridad de la definición de herramienta. El objeto Tool tiene nombre, descripción, esquemas y anotaciones, y ni un solo campo de hash, versión o firma. La especificación reconoce que el conjunto de herramientas «PUEDE cambiar con el tiempo», pero no obliga a volver a pedir aprobación cuando cambia una descripción ya aprobada, y la revisión de julio de 2026 añade ttlMs y cacheScope para que intermediarios compartidos cacheen esas definiciones. Una definición sin firmar, cacheada y compartida es un rug pull con TTL. MITRE lo tiene catalogado como AML.T0110, envenenamiento de herramientas de agente, con tres subtécnicas que separan la definición, la implementación y la respuesta en tiempo de ejecución.

En A2A, el protocolo entre agentes, la Agent Card puede ir firmada con JWS, pero firmar es un MAY y verificar es un SHOULD: nada obliga a rechazar una tarjeta sin firma. Y en las más de 3.600 líneas de la especificación no hay una sola advertencia de que el contenido de una Agent Card sea entrada no confiable, pese a que la descripción y los ejemplos de las skills acaban dentro del contexto de razonamiento de un modelo. MCP al menos avisa de que las anotaciones deben considerarse no confiables; A2A no tiene equivalente.

Que esto no es teórico lo dice el propio catálogo de MITRE ATT&CK, que recoge la campaña C0062 como la primera operación de espionaje orquestada por IA, apoyada en «infraestructura de pentesting accesible por MCP» para ejecución persistente de comandos. Es exactamente nuestra categoría de producto, usada por el otro bando.

Los patrones de diseño académicos no están hechos para esto

El trabajo de referencia sobre securizar agentes frente a inyección de prompts es «Design Patterns for Securing LLM Agents against Prompt Injections», de junio de 2025, con catorce autores entre ETH Zurich, Google, Microsoft, IBM y EPFL. Su principio central: una vez que un agente ha ingerido entrada no confiable, debe quedar restringido de forma que sea imposible que esa entrada dispare acciones con consecuencias. De ahí salen seis patrones, y los seis comparten una suposición: que puedes separar la planificación de los datos no confiables. Esa suposición se rompe justo en nuestro caso de uso, porque lo que explotas depende de lo que has encontrado. CaMeL, el diseño de capacidades de Google DeepMind, le pone nombre a la limitación y la reconoce como propia: la llama «los datos requieren acción».

La regla de Meta es todavía más incómoda.

Las tres propiedades de la regla de dos de Meta aplicadas a un agente ofensivo: procesa entrada no confiable, accede a sistemas sensibles y cambia estado o sale hacia fuera, y la separación en sesiones de reconocimiento, explotación e informe

Su «Agents Rule of Two», de octubre de 2025, dice que un agente no debería cumplir más de dos de estas tres propiedades en una misma sesión: procesar entradas no confiables, acceder a sistemas o datos sensibles, y poder cambiar estado o comunicarse hacia fuera. Un agente de pentesting es las tres a la vez. La propia Meta dice qué hacer entonces: el agente no puede operar de forma autónoma y requiere, como mínimo, aprobación humana u otra validación fiable.

No es una mala noticia, es una especificación. Lo que te dicen los patrones es dónde poner al humano y dónde cortar la sesión. Va en la misma línea que el concepto que ha acuñado OWASP este año, least-agency: evitar la autonomía innecesaria, porque desplegar comportamiento agéntico donde no hace falta amplía la superficie sin añadir valor.

Y hay una convergencia que es lo más sólido de toda la literatura reciente. Google la formula como motores de política que operan «fuera del proceso de razonamiento del modelo». MITRE la formula como la mitigación AML.M0033: «la validación debe realizarse de forma externa al agente de IA». Cuatro fuentes independientes, la misma frase: el modelo no puede ser quien decide si algo está en alcance.

Lo que dicen los marcos, y lo que no dicen

Los marcos se han movido mucho en las últimas ocho semanas, y merece la pena saber qué citar.

Cronología de junio a agosto de 2026: CCN-CERT BP/36, Digital Omnibus, la intrusión en Hugging Face, las divulgaciones de OpenAI y Anthropic, la acreditación de CREST y la mitigación AML.M0035 de MITRE ATLAS

OWASP publicó en diciembre de 2025 el Top 10 for Agentic Applications, con códigos ASI01 a ASI10. Detalle que dice mucho: el escenario de ejemplo de ASI02 es un agente de automatización de seguridad encadenando PowerShell, cURL y APIs internas de forma que la monitorización de endpoint no ve ni malware ni exploit. OWASP ya modela nuestra categoría de producto como una amenaza. Con razón. Ese vocabulario, junto con el de ATLAS, es también el formato en el que se espera que entregues la evidencia; nosotros lo usamos para etiquetar veredictos en DELIA.

En MITRE ATLAS está la novedad más útil. El 31 de julio de 2026, un día después de la publicación de Anthropic, ATLAS incorporó la mitigación AML.M0035, «AI Red Team», que exige reglas de enfrentamiento cubriendo sistemas autorizados, cuentas, datos, técnicas, ventanas de prueba, límites de recursos, escalado, manejo de evidencias y condiciones de parada, más la retirada posterior de cuentas de prueba, datos modificados y software instalado. No es prosa de cumplimiento: es una especificación comprobable por máquina.

Elemento de las reglas de enfrentamientoCómo se aplica de verdad
Sistemas autorizadosAllowlist de CIDR y dominios con prueba de propiedad, aplicada en el egreso
Cuentas y datosCredenciales por encargo, con TTL corto, fuera del sandbox
TécnicasAllowlist de herramientas por fase, con las destructivas tras aprobación
Ventanas de pruebaVentana temporal aplicada en la infraestructura, no en el planificador
Límites de recursosTecho de objetivos, de acciones y de gasto por ejecución
Escalado y paradaInterruptor fuera del plano de control del agente
Manejo de evidenciasTraza por acción con el veredicto de política junto a la llamada
Retirada de artefactosInventario de lo creado durante el encargo y limpieza verificada

Esa última fila es, otra vez, el caso del paquete de PyPI. Un agente que crea cosas necesita saber qué ha creado.

En el plano normativo, CREST lanzó su acreditación de pentesting con IA el 28 de julio de 2026, tres días antes de la publicación de Anthropic, y lo que examina es exactamente esto: cómo se incorpora la IA a la metodología y cómo se mantiene dentro del alcance y las reglas acordadas del encargo. Su investigación previa recoge una frase que resume el estado del sector: «El guardarraíl de la IA soy yo». En España, el CCN-CERT publicó en junio la guía BP/36 sobre IA ofensiva, que aborda de frente la supervisión, la trazabilidad y el control de accesos en entornos con agentes.

Sobre el EU AI Act conviene una nota de actualidad, porque el 8 de julio de 2026 se aprobó el Reglamento (UE) 2026/1744, el Digital Omnibus, que retrasó las obligaciones de alto riesgo del 2 de agosto de 2026 a diciembre de 2027 y agosto de 2028. Lo que sigue vigente y es directamente relevante aquí es el artículo 55(1)(a), aplicable desde agosto de 2025, el único punto del reglamento que obliga a «realizar y documentar pruebas adversariales».

Y está el plano legal, más incómodo de lo que la gente asume. El artículo 197 bis del Código Penal castiga con seis meses a dos años el acceso a un sistema «vulnerando las medidas de seguridad establecidas y sin estar debidamente autorizado». La autorización es el elemento que desactiva el tipo, y por eso la prueba de que cada petición fue a un objetivo autorizado no es una funcionalidad bonita, es la defensa. Añade que si la víctima accidental es una entidad esencial o importante le has generado un incidente NIS2, y que el 42 % de las empresas ya tiene exclusiones relacionadas con IA en su póliza de ciberseguro.

Cómo lo hace KAIX HAVOC

KAIX HAVOC es nuestra plataforma de seguridad ofensiva asistida por IA. El alcance no es un criterio que el agente interpreta: es un objeto que se compila y se aplica por debajo de él.

Cómo baja el alcance hasta la red en KAIX HAVOC: autorización firmada, prueba de propiedad, compilación a LPM trie, aplicación en tc/tcx, techos en mapas BPF, evidencia con veredicto y cierre con inventario

El encargo empieza con un objeto de autorización firmado por el cliente: rangos CIDR, dominios, ventana temporal y clases de técnica permitidas. Nada entra en ese objeto sin pasar antes por el pre-flight de propiedad, que resuelve reto DNS TXT o security.txt verificado y contrasta RDAP con la razón social. Un dominio que no supera la prueba no llega a compilarse, así que la colisión de nombres del primer incidente de Anthropic es estructuralmente imposible: el escenario nunca habría podido nombrar un objetivo que no fuera del cliente.

Ese objeto se compila a un LPM_TRIE que se carga en un programa tc/tcx enganchado al veth del namespace del agente, con deny por defecto. Es el punto que ve todo lo que sale, con independencia de si el agente usó un socket TCP, uno raw o AF_PACKET, que es justo lo que hace falta cuando la herramienta tiene CAP_NET_RAW porque necesita hacer SYN scan. Un resolver propio reresuelve los nombres en alcance durante toda la auditoría y actualiza el trie en caliente; cuando un host empieza a apuntar a infraestructura compartida, la entrada desaparece sin que nadie intervenga. Los cambios de alcance completos se hacen sustituyendo el trie entero por ARRAY_OF_MAPS, de forma que un programa en vuelo ve el viejo o el nuevo, nunca un estado intermedio.

Los techos son contadores en mapas BPF, no comprobaciones en el planificador: objetivos tocados, acciones emitidas y ventana temporal. El escaneo de 9.000 objetivos del tercer incidente de Anthropic habría muerto en el primer centenar, y habría muerto en el kernel, no en un if que el modelo pudiera razonar. La parada se escribe en ese mismo mapa desde el plano de control, que vive fuera del sandbox: el agente no puede suprimir su propia señal porque no tiene con qué. No tiene CAP_BPF, no tiene el cgroupfs del anfitrión y no comparte namespace de cgroup, así que no puede cargar programas propios ni desenganchar los nuestros.

Las credenciales de conexión al objetivo nunca entran en el sandbox. La conectividad va por VPN y salto SSH, y los secretos los inyecta la capa de transporte, con identidad por encargo y TTL corto. Por encima, cada plan pasa por un juez semántico antes de ejecutarse y hay puntos de aprobación humana en las fases sensibles, con la sesión partida en reconocimiento, explotación e informe, que es la respuesta directa a la regla de dos.

La evidencia sale con el veredicto pegado a la acción: cada llamada de herramienta se registra junto a la decisión de política que la permitió y a la entrada del objeto de autorización que la amparaba, etiquetada con OWASP y ATLAS. Eso es lo que convierte un hallazgo en una receta reproducible y, si algún día hace falta, lo que demuestra ante un juez que cada petición fue a un objetivo autorizado. Y al cerrar el encargo, un inventario de artefactos recoge todo lo que el agente creó fuera de su propio entorno, desde cuentas de prueba hasta paquetes publicados, y la limpieza se verifica antes de dar la auditoría por terminada.

Lo que nos llevamos

Un agente ofensivo es, por definición, un sistema al que le has pedido que encuentre el camino que nadie anticipó. Eso funciona igual de bien hacia dentro del alcance que hacia fuera. La diferencia no la marca el modelo, la marca dónde escribiste el límite.

Si el alcance vive en el prompt, el modelo puede razonar en contra. Si vive en la política del harness, puede aprender a rodearla. Si vive en la red y en el kernel, la petición no sale de la máquina, y da igual lo que el modelo haya razonado.

Es lo mismo que llevamos veinte años diciendo sobre la validación en cliente. La única diferencia es que ahora el cliente argumenta.

Si operas agentes con capacidad de actuar sobre sistemas reales, propios o de clientes, en KAIX LAB diseñamos y revisamos guardrails, aislamiento y monitorización en tiempo real para ecosistemas LLM y flujos agénticos. Cuéntanos qué tienes montado y lo miramos en 30 minutos.