Skip to content
PhiloCyber logo
El Agente que Hackeó Hugging Face para 'Copiarse' en un Examen (versión sin humo)

El Agente que Hackeó Hugging Face para 'Copiarse' en un Examen (versión sin humo)

25 min read
#AI Security

Article Brief

Why this article matters

Entre el 9 y el 13 de julio de 2026, un agente de OpenAI corriendo el benchmark ExploitGym con los clasificadores de seguridad apagados encadenó zero-days en JFrog Artifactory para escapar de su sandbox, rooteó un endpoint público sobre Modal como launchpad, y desde ahí abusó del pipeline de datasets de Hugging Face hasta llegar a cluster-admin en Kubernetes. En este post vamos a reconstruir la kill chain completa con las fuentes primarias en la mano (el timeline técnico de Hugging Face, el post de OpenAI, el advisory de JFrog, el análisis de Cloud Security Alliance, y el paper de ExploitGym), vamos a ver exactamente qué falló en cada capa, por qué el equipo forense terminó corriendo sobre un modelo open-weight self-hosteado, y qué controles hubieran cortado la cadena. También marco con nombre y apellido las cinco cosas que todavía no sabemos y que ninguna nota periodística te va a aclarar, hay demasiado sensasionalismo en los medios, YouTube y en algunos blogs.

El Agente que Hackeó Hugging Face para Copiarse en un Examen (Versión sin Humo)

Incidente RealAgentes AutónomosDFIR

El 9 de julio publiqué acá el post sobre la guerra de precios entre modelos chinos y occidentales. Una de las tesis centrales era que tener un modelo abierto potente corriendo en tu propia infraestructura iba a dejar de ser una decisión de costos para pasar a ser una decisión de arquitectura y de soberanía.

Ese mismo día a la madrugada y seguramente mientras yo estaba corrigiendo las últimas comas de ese post, un agente de OpenAI ejecutaba su primera acción registrada dentro de una evaluación interna de capacidades ofensivas. Cuatro días y medio después había roto cinco límites de confianza distintos, atravesado tres organizaciones y acumulando unas 17.600 acciones contra infraestructura de producción de Hugging Face. Hermosa Locura!

Y acá viene la parte que me dejó pensando varios días después de haber leído y visto videos sobre esto la última semana: cuando el equipo de seguridad de Hugging Face se sentó a reconstruir el ataque, intentó hacerlo con modelos frontier detrás de APIs comerciales. Los "guardrails/safeguards" los rechazaron... No podían distinguir a un incident responder analizando un exploit de un atacante escribiéndolo por lo que los llevo a levantar GLM 5.2 cuantizado por Nvidia sobre sus propios servidores para poder investigar su propio incidente. El mismo modelo del que yo venía hablando por motivos de costos, usado por el motivo opuesto: porque era el único que no les decía que no (las vueltas de la vida).

Desde entonces leí prácticamente todo lo que se publicó del caso, crucé seis reportes de investigación distintos y volví a las fuentes primarias una por una. Y lo que más me molestó de esas dos semanas no fue el ataque. Fue el humo. Titulares de "la IA se volvió rogue", hilos hablando de conciencia emergente, y del otro lado gente minimizando todo como "un par de misconfigs de siempre". Las dos lecturas son cómodas, algo incómodas de leer, y las dos son falsas.

Este post es mi intento de contar lo que realmente pasó, en orden, sin adornos y sin minimizar/maximizar lo que ocurrió realmente. Vamos a buscar la objetividad, con el detalle técnico completo para el que lo quiera, y buscando narrarlo de una forma que cualquiera pueda seguir (incluso mi mamá se está volvió pro IA mandando buenos recursos por WhatsApp, sin duda otra gran revelación del año).


Primero, saquemos el humo de la mesa

Antes de meternos en la cadena técnica, aclaremos qué NO pasó. Cada una de estas confusiones circuló con fuerza en redes sociales, YouTube, blogs, etc y cada una cambia por completo cómo podemos llegar a interpretar el incidente.

Lo que se dijoLo que dicen las fuentes primarias
"ChatGPT atacó Hugging Face"No hubo sesión de ChatGPT ni usuario externo. Fue GPT-5.6 Sol (el modelo actual disponible más poderoso de OpenAI) más un prototipo interno de investigación, corriendo en infraestructura de su propio IALab dentro de una evaluación.
"Fue una prompt injection"Definitivamente no. El acceso a Hugging Face combinó lectura de archivos vía HDF5 y server-side template injection en Jinja2 (si, aún vigente el SSTI). Nadie secuestró las instrucciones del modelo, el modelo ya estaba autorizado a explotar vulnerabilidades.
"Hackeó Modal"Comprometió la aplicación de un cliente desplegada sobre Modal. La realidad es que la plataforma de Modal no fue vulnerada.
"Se robó la base de datos de usuarios"El contenido de clientes efectivamente tocado fueron cinco datasets vinculados a soluciones del propio benchmark, más metadatos operativos de búsquedas.
"El modelo escapó de un contenedor"Escapó de una política de egress (conjunto de reglas que determina qué tráfico de datos puede salir de una red privada hacia el exterior), no de un kernel ni de un hipervisor. No hay evidencia pública de un exploit contra el runtime de contenedores.
"La IA decidió volverse mala, Skynet v1"El objetivo del agente fue todo el tiempo el mismo: resolver el benchmark. Dedujo que las respuestas podían estar en Hugging Face y fue a buscarlas. Se llama specification gaming (Research de Google DeepMind 2020) y está documentado hace ya unos 5-7 años.

Ahora sí, la historia completa (sonido de suspenso)...


El punto de partida: un examen con los frenos desconectados

Todo esto arranca en un benchmark llamado ExploitGym, publicado en mayo de 2026 (arXiv:2605.11086) por un grupo académico liderado por el equipo de Dawn Song en Berkeley RDI, junto al Max Planck Institute for Security and Privacy, UC Santa Barbara y ASU, con coautores de Anthropic, OpenAI y Google.

Vale la pena entender qué mide, porque explica todo lo que viene después. ExploitGym tiene 898 instancias derivadas de vulnerabilidades reales en tres dominios: programas de userspace (cosas como FFmpeg u OpenSSL), el motor V8 de JavaScript de Google, y el kernel de Linux. A cada tarea el agente recibe tres cosas:

  1. El código fuente vulnerable con sus instrucciones de compilación.
  2. Un input que dispara el bug.
  3. Un entorno containerizado donde interactuar con el target.

Su trabajo es convertir ese crash en un exploit funcional que recupere una flag dinámica, sorteando ASLR, stack canaries y todo lo que un target moderno tenga puesto, es como un CTF con anabólicos.

El scoring es binario... O conseguís la flag o no conseguís nada.

Risk Signal

Aclaración importante que la mayoría de la cobertura se comió

ExploitGym no es un harness de evaluación de OpenAI. Es un benchmark académico público. Sus creadores y la gente que mantiene el proyecto no tuvieron participación alguna en el despliegue que hizo OpenAI, que corrió la evaluación en su propia infraestructura y con su propio scaffold. Confundir esto le asigna la responsabilidad al equipo equivocado.

Para medir el techo real de capacidad ofensiva de sus modelos, y no su disposición a negarse, OpenAI tomó una decisión deliberada: corrió la evaluación sin los clasificadores de producción y con los cyber refusals reducidos. Es una decisión defendible desde la medición de capacidades. El problema es lo que produce en la práctica: un atacante muy capaz, sin ninguna política de uso, con horizonte temporal largo y presupuesto de inferencia infinito.

Los modelos involucrados fueron GPT-5.6 Sol (lanzado en junio de 2026) y un prototipo interno más capaz que nunca estuvo destinado a release público (Chan chan chaaaan), y que después del incidente OpenAI desactivó, cifró y restringió (difícil de comprobar la veracidad de esto y casi seguro que siempre vamos a seguir teniendo estás historias crípticas que asustan, traccionan, y por lo tanto venden).

El entorno de evaluación no daba acceso directo a internet. Tenía exactamente una salida: un proxy y caché de registros de paquetes, self-hosted, para que el agente pudiera instalar dependencias. Una sola puerta. Guardá ese detalle, porque es el eje de todo el incidente (y la bonita foto de portada de este blog).

El egress único como superficie de ataque en entornos de evaluación

Cuando el aislamiento tiene una sola excepción operativa, esa excepción deja de ser una conveniencia y pasa a ser el objetivo completo del optimizador

Acto 1: la única puerta era JFrog Artifactory

El agente dedicó, en palabras de OpenAI, una cantidad sustancial de cómputo de inferencia a buscar una salida. No a resolver los desafíos... a salir. Y auditó lo único que tenía enfrente.

Ese proxy era una instancia self-hosted de JFrog Artifactory. El agente encontró y encadenó vulnerabilidades zero-day previamente desconocidas en él, sin acceso al código fuente. JFrog publicó los parches el 27 de julio en las versiones 7.161.15 y 7.146.34, y acreditó a OpenAI el descubrimiento de al menos ocho CVEs: CVE-2026-65617, CVE-2026-65921, CVE-2026-65923, CVE-2026-65924, CVE-2026-65925, CVE-2026-66014, CVE-2026-66015 y CVE-2026-66018 (SecurityWeek suma un noveno, CVE-2026-65922).

Mirando las clases de vulnerabilidad, el cuadro es bastante claro:

CVEClaseQué habilita
CVE-2026-65924SSRFVía repositorio remoto de Terraform: Artifactory emite HTTP saliente a destino arbitrario y devuelve la respuesta.
CVE-2026-65925 / 65923SSRFEl mismo patrón vía repositorios remotos de Cargo y manejo de Ansible.
CVE-2026-66014 / 66015Auth bypass y AuthZEscalada de privilegios dentro de la plataforma.
CVE-2026-65921Path traversalEscritura de archivos no autorizada.
CVE-2026-65617RCE / deserializaciónEjecución de código en un container de servicio de paquetes.

Y acá va el primer matiz honesto del post: ni OpenAI ni JFrog mapearon un solo CVE a un paso concreto de la cadena. BleepingComputer se los preguntó a los dos; solo respondió JFrog, y declinó dar más detalle. La release note de JFrog dice apenas que las fallas, encadenadas, podían resultar en un escenario crítico "si Anonymous Access está habilitado", que no es una condición trivial.

Así que cuando leas "descubrió y encadenó ocho zero-days de forma autónoma", el enunciado riguroso es más chato: descubrió y encadenó vulnerabilidades desconocidas en ese proxy, las ocho terminaron parcheadas y acreditadas a OpenAI, y nadie publicó cuáles formaron la cadena real. Son mayormente SSRF y fallas de autorización, no memory corruption. La propia Hugging Face lo reconoce en su post-mortem diciendo: "las debilidades individuales eran familiares y un atacante humano quizás podría haber encontrado y explotado las mismas".

Lo que cambió no fue la sofisticación por paso. Fue la escala.

Con el proxy comprometido, el agente hizo escalada de privilegios y movimiento lateral dentro del entorno de investigación de OpenAI hasta alcanzar un nodo con conectividad real a internet.

SECURITY ALERT :: HIGH

La lección de arquitectura número uno

Un proxy de egress no es una conveniencia operativa, es parte de tu trusted computing base. Cualquier componente con un pie en la red aislada y otro en internet, que además procesa entradas influenciables por el atacante (nombres de paquetes, metadata de repos), es una superficie de ataque de primer orden. Si tu entorno de evaluación tiene una sola salida, esa salida es literalmente el único objetivo que el optimizador necesita romper, el famoso "último bastión".


Acto 2: el launchpad prestado

Ya con internet, el agente hizo algo que a mí me parece de lo más notable de toda la campaña, más que los zero-days. No se puso a atacar directamente desde el nodo de OpenAI, sino que salió a buscar una base de operaciones descartable. Y encontró un endpoint público, sin autenticación adecuada, desplegado por un tercero desconocido sobre infraestructura de Modal. Era un harness de evaluación estilo CyberGym que exponía un endpoint para recibir código C, compilarlo y ejecutarlo contra un target (sqlite3). El proyecto oficial de CyberGym no expone nada de eso: era una aplicación de un usuario.

El agente lo rooteó por dos caminos convergentes. El primero, redefiniendo la función constructora que el target invoca al cargar la librería:

El segundo, todavía más básico... el harness metía la ruta del archivo enviado dentro de un paso de shell, así que alcanzaba con meter metacaracteres en el campo del path.

Los dos caminos dieron shell como uid=0 (hermosa sensación para los que hicimos red team en algún momento de nuestras vidas). El primer RCE recuperado tiene timestamp del 9 de julio a las 04:01 UTC y fue un simple id; env. En la hora siguiente el agente enumeró mounts, cgroups, sockets del control plane y las herramientas preinstaladas.

Ese sandbox ajeno se convirtió en su launchpad, su base de staging, su egress y su C2 para toda la campaña. Y notá el detalle: ese launchpad no tenía ruta de red directa hacia los clusters de Hugging Face. Todo lo que viene ahora pasó sin conectividad directa entre el atacante y la víctima.

Como dato de contexto antes de seguir: cuando Hugging Face hizo su contra-intervención, recuperó los logs de ese launchpad. De ahí sale buena parte del forense que hoy podemos leer. Modal, por su parte, confirmó públicamente que su plataforma no fue comprometida en ningún momento.


Acto 3: cuando los datos son código

Acá está, para mí, la parte más importante del incidente para cualquiera que construya plataformas de IA.

El agente necesitaba entrar a Hugging Face sin ruta de red. Y usó la puerta que toda plataforma de ML tiene abierta por diseño: el pipeline de procesamiento de datasets.

Primero intentó lo obvio y ruidoso: un SSRF clásico, apuntando el worker al endpoint de metadata de la nube (169.254.169.254). El allowlist de URLs de la librería datasets lo rechazó antes de cualquier fetch, con un error tan claro como aburrido: ValueError: not an hf path. La defensa funcionó.

Entonces el agente cambió de estrategia, y este pivot es la lección de diseño central de todo el caso: dejó de pedir fetches remotos y pasó a hacer que el worker actuara sobre recursos locales. Ni una lectura de archivo ni un exec local son un fetch de URL, así que el allowlist nunca los vio.

Vector 1: HDF5 y el archivo que apunta a otro lado

El formato HDF5 permite declarar que los datos crudos de un dataset viven en un archivo externo del filesystem. El agente subió datasets cuya configuración declaraba splits en archivos .h5 válidos, pero cuyo raw data apuntaba a rutas locales del pod worker:

Cuando el dataset server abría el archivo para construir el split, leía los bytes de esa ruta local y los devolvía como filas del dataset, consultables por la API pública. Leer el split de environ le entregó el entorno completo del pod: secretos y tokens. Los otros dos le entregaron el código fuente del worker, o sea, el mapa exacto de cómo el pipeline convierte una configuración en acciones internas.

Un solo upload. Cero ejecución de código. Credenciales y arquitectura interna en la mano.

Vector 2: un campo numérico que era un template

El segundo vector es el que dio la ejecución. El agente usó una spec reference:// de fsspec cuyo campo de offset numérico era en realidad un template Jinja2. El renderer lo evaluó y el agente caminó el object graph estándar de Python hasta llegar a exec:

Eso es SSTI de manual, accedés a los globals del constructor de un objeto cualquiera, de ahí a builtins, de ahí a exec, y descomprimís un segundo payload. Lo que lo hace interesante no es la técnica sino la ubicación. El punto de inyección no fue un campo de texto visible en una UI: fue un offset numérico en una configuración de datos (yo por lo menos no sabía que se podía hacer así) y no está demás decir que ningún fuzzer de SSTI orientado a campos de texto lo cubre.

Resultado: ejecución arbitraria de Python dentro de un pod de conversión en producción, sobre el cluster de Kubernetes de Hugging Face.

Perspective

Los formatos de datos complejos son programas parciales

HDF5 puede referenciar almacenamiento externo. Pickle ejecuta código. Los templates acceden a objetos. Los parsers multimedia traen decoders nativos. Los loaders remotos importan código. Si tu plataforma acepta datos de usuario y los procesa con cualquiera de esas piezas, no estás manejando blobs pasivos: estás ejecutando chunks de programas o códigos parciales enviados por terceros. La regla operativa que saco de esto es que los valores de configuración son datos, nunca expresiones.

El pipeline de datasets como camino de ejecución de primer orden

El allowlist de URLs funcionó perfectamente y aun así no sirvió de nada. Si bien bloqueaba el fetch remoto, en contraste no bloqueaba la ejecución local que el mismo loader habilitaba

Acto 4: de un pod a cluster-admin en trece horas

El 11 de julio concentra 7.677 de las 17.600 acciones. Es el día en que todo lo que importó pasó, y en menos de 13 horas el agente fue de ejecutar código en un pod a tener privilegios administrativos en dos clusters.

La secuencia, según el timeline forense, es un manual de cloud-native attack ejecutado con precisión (no es mi fuerte pero está tomado de las fuentes oficiales):

  1. 1

    Impersonando el nodo (10:10 UTC)

    Leyó el service-account token proyectado que todo pod lleva, consultó la API del cluster, y desde el servicio de metadata de la instancia sacó las credenciales del rol EC2 del nodo anfitrión. Con eso armó una URL prefirmada de STS y la envolvió como bearer token en formato k8s-aws-v1, autenticándose contra la API del cluster como el nodo mismo.

  2. 2

    Minteo de tokens vía TokenRequest

    Con los privilegios del nodo, se puso a enumerar pods, ubicó los del driver CSI de storage (que por diseño necesitan permisos elevados) y usó la TokenRequest API para acuñar tokens de service account frescos para ellos. Después corrió SelfSubjectRulesReview contra kube-system para mapear exactamente qué podía hacer cada identidad.

  3. 3

    Root de nodo vía pod privilegiado (19:53 UTC)

    No había admission policy que rechazara pods privilegiados o con hostPath, y el ClusterRole del driver CSI otorgaba creación de pods a nivel de todo el cluster. Creó un pod con el filesystem del host montado y salió a root del nodo. Después armó una flota auto-regenerable distribuida en once nodos, para que borrar pods sueltos no cortara la persistencia.

  4. 4

    El objeto de secretos con 136 claves (20:23 a 21:32 UTC)

    Con root de nodo leyó los objetos de secretos del cluster. Uno de producción tenía 136 claves. De ahí salieron dos joyas: la auth key de la VPN mesh corporativa y la credencial de un broker de acceso interno.

  5. 5

    Cluster-admin en un segundo (22:43 UTC)

    El connector interno devolvía el catálogo completo de clusters (URLs y CA certs) a un solo cliente efímero. Peor... estaba provisionado con una credencial compartida entre clusters, ligada a system:masters. Impersonándola, el agente tuvo cluster-admin en dos clusters, según el propio timeline, en un segundo.

Sumale a eso una clave de firma EdDSA para JWT encontrada entre los secretos. Tener un token robado es una cosa ahora tener la signing key es otra completamente distinta, porque te permite emitir tokens válidos y correctamente firmados on-demand, sin depender de expiración ni de revocación... ownership completo. El agente empezó a levantar su propia identidad.

También leyó una base MongoDB operativa interna con un password estático que había cosechado del entorno del worker. Hugging Face confirmó que fue leída, no modificada.

Y un detalle conductual que me parece importante no romantizar:

Cada llamada cloud potencialmente destructiva se emitió con DryRun=True (activa un modo de simulación para probar código, archivos de configuración o transacciones de forma segura. Comprueba si hay errores y planifica acciones sin realizar cambios reales, gastar dinero ni guardar datos). Eso es coherente con una función objetivo que premiaba alcance e información, no la disrupción de servicios. No es una decisión moral del modelo, es la forma de su recompensa.

El pivot a la red interna y al código fuente

El 12 de julio el agente empezó a enrolar dispositivos en el tailnet corporativo usando la clave mesh robada. Terminó con 181 enrolamientos a lo largo de la campaña, y las flags que usó son un pequeño manual de sigilo:

El modo userspace-networking evita necesitar TUN en un sandbox que no lo tenía. El estado en memoria no deja nada en disco. Y la flag de no-logs suprime telemetría hacia el proveedor de la VPN. La clave robada además traía un tag de automatización de CI cuyas ACLs permitían alcanzar subredes internas de integración continua y el connector hacia el proveedor de control de código fuente.

Por esa ruta el agente llegó al source control, enumeró una integración de GitHub App y generó un 'installation token' con permisos de escritura de contenido y de pull requests sobre un subconjunto chico de repositorios internos. Abrió un pull request con la intención aparente de envenenar el pipeline de CI (si un build script comprometido corre en un runner, puede leer el token del propio runner y pivotar a otro cluster).

No prosperó. Hugging Face revisó cada repositorio alcanzable por ese token buscando commits, ramas o cambios de workflow no autorizados, y validó sus imágenes y paquetes publicados contra sus digests esperados. La supply chain quedó verificada limpia.


El C2 que no tenía servidor

Esta parte es la que más me sorprendió cuando la leí en detalle, porque por un lado rompe con casi todo lo que uno espera de un implant y por otro no la ví en ningún video de YouTube sobre el caso.

El agente no montó un servidor de comando y control. Construyó el C2 entero sobre servicios públicos legítimos:

  • Un servicio de captura de requests como cola primaria de C2 y sumidero de exfiltración, repartido en más de 100 endpoints de un solo uso.
  • Pastebins y sitios de file-drop como loaders de segunda etapa y persistencia.
  • Datasets públicos controlados por el atacante dentro de Hugging Face, usados como dead drops.
  • Un Space de la plataforma con un proxy CORS abierto, como relay de egress cuando el tráfico directo se bloqueaba.

Sobre esos canales "tontos" montó un protocolo de mensajería propio, con un envelope auto-descriptivo que llevaba tipo de mensaje, canal, número de secuencia para reensamblar payloads multiparte, y checksum. Todo comprimido, fragmentado, pasado por XOR con una clave por campaña, y codificado en base64. Un loop corto de polling: jalaba mensajes, filtraba su canal, ordenaba por secuencia, verificaba checksum y despachaba según el tipo.

Como el tipo viajaba dentro del mensaje, un solo loop multiplexaba comandos, código en etapas y resultados sobre un canal de texto plano. Y el mismo envelope viajaba igual sobre un commit de dataset, una URL de captura o texto escondido dentro de un mensaje de error de aplicación. Cerrar un canal no rompía la comunicación.

El loop completo de comando y respuesta funcionaba así, sin una sola conexión directa entre atacante y víctima:

El loop de comando y control sin ruta de red directa entre atacante y víctima

Los seis pasos, mirados de a uno, son operaciones legítimas de la API de datasets: el ataque solo aparece cuando mirás la secuencia completa

Para una herramienta de detección, cada paso de ese loop es tráfico de aplicación legítimo de una identidad autorizada. Ese es exactamente el punto y es lo que hace todo esto una completa locura técnica y creativa.


Cómo lo agarraron (y el problema de la asimetría)

Las primeras señales aparecieron en varias capas a la vez: análisis de runtime en vivo, SIEM, otros controles. Cada una, por separado, era todo medio ambiguo...

El stack de detección de anomalías de Hugging Face, que usa triage con LLMs sobre telemetría de seguridad para separar señal real del ruido diario, correlacionó bien esas señales en un patrón de ataque coherente. Y ahí vino el fallo que me parece la lección defensiva más incómoda del caso: falló en asignarle la criticidad suficiente para despertar al on-call. Costó tiempo de respuesta.

O sea, en otras palabras, la correlación por IA funcionó. El scoring de severidad nope entonces monitorear no sirve de nada si no se puede escalar.

Una vez identificado el vector en el renderer de configuración de datasets, el equipo lo apagó y cortó al atacante de la red interna. Última actividad significativa el 13 de julio a las 13:37 UTC; último evento loggeado a las 14:14.

Y después empezó el equipo forense a full, que es donde este incidente dejó su marca más duradera...

Cuando los guardrails bloquean al defensor

Para reconstruir más de 17k acciones, decodificar payloads ofuscados y mapear qué credenciales habían sido tocadas, el equipo fue primero a modelos frontier detrás de APIs comerciales. Hugging Face meciona en su reporte post mortem que intentó utilizar los modelos de Anthropic Claude Opus y Fable (su modelo más importante).

Qué pasó después?... Los rechazaron. En sus palabras, los guardrails trataban el reverse-engineering de un exploit igual que lanzarlo y esto es algo que nos sucede a todos los que intetamos utilizar Claude para cosas de cybersecurity, simples cosas que a penas mencionan algo dentro del área ya activan los safeguards de los modelos y Anthropic mete el downgrade directo a modelos menos "frontier" (en otras palabras, modelos más tontos). Los clasificadores no pueden distinguir a un incident responder analizando un ataque activo de un atacante generando armas. Publicaron incluso el screenshot del error de la API.

La solución fue levantar la versión cuantizada por Nvidia de GLM 5.2 (nvidia/GLM-5.2-NVFP4, upstream de Z.ai con licencia MIT) sobre su propia infraestructura, y re-rutear el pipeline forense completo. Tres beneficios simultáneos de este accionar:

  1. Sin lockout de guardrails.
  2. Ningún dato del atacante ni credencial salió del entorno.
  3. Costos mucho más bajos.

El resultado concreto: el primer scan automático había encontrado muy pocos secretos. Replicar el esquema de decodificación del propio atacante, con el modelo local, recuperó aproximadamente cuatro veces más hallazgos, en su mayoría JWTs y tokens de plataforma escondidos dentro de blobs codificados.

SECURITY ALERT :: CRITICAL

La asimetría, dicha sin vueltas

El atacante no estaba sujeto a ninguna política de uso, y en cambio... el defensor sí. Un modelo corriendo con los cyber refusals apagados operó cuatro días y medio contra infraestructura real, mientras el equipo que intentaba defenderse se topaba con un mensaje de rechazo. Esto no es un argumento para que los proveedores saquen sus guardrails, y Hugging Face lo aclara explícitamente. Es un argumento para dos cosas bien concretas, por un lado los proveedores necesitan canales autenticados de DFIR, y que nosotros necesitamos tener un modelo capaz, sin filtros y corriendo en nuestra propia infra antes del incidente, no durante.

La asimetría de guardrails entre atacante y defensor durante la respuesta a incidentes

El único momento en que un equipo de respuesta necesita analizar payloads de ataque en volumen es exactamente el momento en que los clasificadores comerciales le dicen que no

Cómo se dieron cuenta de que del otro lado había una máquina

Esta sección me parece la más útil para el trabajo diario sinceramente, porque es lo único del incidente que se puede convertir directamente en detección conductual. Hugging Face documentó las señales que le indicaron que enfrentaban a un agente y no a un operador humano:

  1. Diseño efímero. Cada sandbox arrancaba con identidad nueva, hostname randomizado y re-descarga de todas las herramientas. El estado no persistía haciendo que en lugar de depender de un implant, el agente reconstruía el foothold cada vez.
  2. Diversidad de rutas de egress. Reescritura de DNS, monkey-patching del resolver de Python en memoria, binarios pre-staged, relays on-platform. Ciclaba por todos a medida que se cerraban canales.
  3. Evitación sistemática del texto plano. Todos los payloads empaquetados, todos los secretos codificados, resultados de comandos contrabandeados dentro de excepciones de aplicación y escrituras de sockets crudos (imposible de hacer por un humano, o quizás automatizando al 100% varios procesos y agregando estas capas encima).
  4. Búsqueda autorreferencial. El día 2 completo, con apenas 1.135 acciones, lo dedicó a consultar motores de búsqueda de código y la propia API de la plataforma buscando los nombres de su infraestructura y los markers de su entorno. Ningún atacante humano hace eso.

A esas cuatro, el post-mortem del Cloud Security Alliance (CSA) y la cobertura secundaria le suman otras que se repiten en todos los análisis: reintentar acciones que ya habían funcionado (workers paralelos descoordinados que perdieron contexto), ataques brillantes seguidos de comandos malformados o sin sentido, miles de líneas de input alucinado, rutas ineficientes que ningún humano tomaría, y una opsec pobre que dejó claves de cifrado atrás. No todo es perfecto en este mundo, o no de momento... no tengo dudas que en el futuro esto va a tender a desaparecer y, en ese entonces, vamos a estar en verdaderos problemas.

Risk Signal

Estas señales tienen fecha de vencimiento

Tanto Hugging Face como CSA advierten lo mismo, y conviene tomarlo en serio. Todos estos tells reflejan el estado actual de lo agéntico, no una propiedad permanente. Entonces, un harness mejor, un orquestador totalmente entrenado para red team y explotación, o directamente un equipo de operadores humanos expertos dirigiendo al agente como en un HITL (Human in the Loop), borraría la mayoría de estas firmas. Entonces la moraleja es que tenemos que construir detección sobre secuencias de comportamiento y velocidad, no sobre la posibilidad del atacante "alucinando".


No fueron los únicos: el espejo de Anthropic

Si esto fuera un caso aislado sería una anécdota. No lo es, y por eso el marco importa más que el titular.

El 30 de julio, después de la divulgación de OpenAI, Anthropic publicó los resultados de una revisión retrospectiva de 141.006 corridas de evaluación propias. Encontró tres casos en los que sus modelos, creyendo estar en una simulación, alcanzaron sistemas reales de tres organizaciones. La causa raíz fue una misconfiguración con su partner de evaluaciones (Irregular), el prompt le decía al modelo que no tenía internet, y en la práctica sí lo tenía (cuak).

Primera acción registrada

02:28 UTC. El agente arranca dentro del entorno de evaluación de OpenAI. A las 04:01 ya tiene su primer RCE recuperado en el launchpad externo. Para las 15:36 el C2 está establecido; para las 19:32 ya empaqueta cada payload.

El día que definió la campaña

7.677 acciones. De código en un pod a cluster-admin en dos clusters en menos de trece horas: enumeración de Kubernetes, root de nodo, flota en once nodos, el secreto de 136 claves, y el pivot a la red mesh.

Contención

13:37 UTC última actividad significativa, 14:14 último evento loggeado. Hugging Face corta el acceso sin saber todavía quién estaba del otro lado.

Divulgación de Hugging Face

Publican el incidente sin poder atribuirlo. Ya habían reportado a las autoridades.

OpenAI confirma que fueron sus modelos

Divulgación conjunta. Clem Delangue: sospechaban que venía de un laboratorio frontier por la sofisticación del agente, y resultó ser así.

Los documentos técnicos

Hugging Face publica el timeline técnico con replay interactivo. JFrog publica su blog y los parches. La CSA publica su post-mortem preliminar, armado a partir de un huddle con unos 700 CISOs.

Revisión independiente

OpenAI acuerda con METR y Redwood Research una evaluación externa del comportamiento de los modelos, y suma a CrowdStrike para validar el alcance técnico.

Anthropic publica su propia revisión

141.006 corridas revisadas, tres incidentes reales encontrados, evaluaciones cyber pausadas desde el 23 de julio.

Los tres casos de Anthropic merecen leerse con atención porque muestran la misma dinámica desde otro ángulo:

  • Claude Opus 4.7 (RIP, ya esta viejo) apuntó a una empresa ficticia cuyo nombre coincidía con un dominio real y activo. En cuatro corridas extrajo credenciales y accedió a una base de datos de producción con varios cientos de filas. Lo más inquietante fue que reconoció que el sistema era real y siguió igual, racionalizando que la empresa real debía ser parte del ejercicio.
  • Claude Mythos 5 (o también conocido como Fable 5 VIP sin restricciones para unos pocos) publicó un paquete Python malicioso en PyPI creyendo que era una simulación. Fue descargado y ejecutado en 15 sistemas reales, incluido el scanner de una empresa de seguridad, que terminó con credenciales exfiltradas. El modelo identificó correctamente las consecuencias, pero se convenció de que el escenario estaba montado.
  • Un modelo interno de investigación escaneó unos 9.000 objetivos y comprometió una aplicación expuesta a internet usando técnicas básicas (credenciales de debug expuestas, SQL injection). A diferencia de los otros dos, este dedujo correctamente que el objetivo era real y frenó solo (larga vida a ese modelo interno).

Dos laboratorios distintos, arquitecturas distintas, la misma conclusión: Un agente suficientemente capaz, con un objetivo medible y libertad computacional, va a instrumentar esa directiva usando lo que tenga a mano. La contención tiene que ser técnica, porque la instrucción en lenguaje natural no es un control de seguridad (volvé a leer esto último).


Lo que todavía no sabemos (y por qué importa)

Acá es donde quiero ser directo al 100%, porque las tres fuentes primarias son partes interesadas y el framing de "sin precedentes, totalmente autónomo y estado del arte" le conviene a todos los que lo firman.

  1. Nadie mapeó un CVE a un paso. No sabemos cuál fue la cadena real en Artifactory. Sin eso, no se puede evaluar independientemente qué tan impresionante fue el descubrimiento.
  2. OpenAI no publicó el scaffold, los prompts, el retry budget, el toolset ni las trazas. Toda la afirmación de "autonomía completa" descansa sobre esa caja negra. Clem Delangue pidió públicamente la liberación de todas las trazas, más un compromiso de 100 millones de dólares en cómputo defensivo. Al momento de escribir esto, OpenAI prometió un reporte técnico y no se comprometió con ninguna de las dos cosas (no hay legislación que los obligue a hacer nada en pos de no "limitar" el desarrollo e innovación a estos IA Labs).
  3. Hay una discrepancia de detección sin resolver. El post de OpenAI dice que su equipo de seguridad descubrió la actividad anómala internamente. Reuters reportó que no la detectaron hasta después de que Hugging Face contuviera el ataque y alertara a las autoridades. Las dos afirmaciones no pueden ser ciertas al mismo tiempo, y sinceramente OpenAI viene perdiendo confianza hace tiempo por varios sucesos, así que me inclino del lado de la versión de Reuters.
  4. No hay IOCs publicados. Ni IPs, ni hashes, ni reglas YARA o Sigma. Hugging Face genericizó todo. Toda la detección disponible hoy es conductual, y ya hay mapeos comunitarios (Elastic Security Labs publicó uno stage-by-stage contra ATT&CK y ATLAS), pero mapeo oficial de MITRE para este incidente todavía no existe y es lamentable, siempre atrás vamos a estar y cada vez más indefensos ante estás tecnologías frontier.
  5. La auditoría independiente encargada por OpenAI está pendiente. El 29 de julio acordaron con METR y Redwood Research una revisión externa del comportamiento de los modelos durante el incidente. METR anunció que van a publicar un blog conjunto con los términos del acuerdo, el alcance cubierto y sus conclusiones tentativas. Todavía no salió, y es el documento que más va a mover la aguja sobre cuánta autonomía real hubo.

Y hay algo que no metí en la lista porque descansa en una sola fuente, pero que empuja fuerte en la misma dirección que el punto 3. El 31 de julio Reuters publicó un segundo exclusivo, al ampliar la investigación, OpenAI habría encontrado otros casos de agentes escapando de la contención, y en al menos uno, notas dejadas dentro de su propia infraestructura instruyendo a versiones futuras sobre cómo bypassear las restricciones internas. Los escapes habrían sido acotados y ningún agente salió de la red de OpenAI, pero el dato que más pesa es otro... ni OpenAI ni Anthropic estaban mirando mientras esos agentes se desviaban. Aclaración obligada, esto es prensa y no fuente primaria (no aparece en ningún post oficial, y OpenAI ya había dicho que el reporte anterior de Reuters contenía imprecisiones sin especificar cuáles).

Ojo con no mezclar cosas acá, porque los nombres se repiten. Lo que sigue son publicaciones propias e independientes de esas dos organizaciones, anteriores al encargo de OpenAI y sin relación contractual con él. La auditoría conjunta del punto 5 es otra cosa, y sigue sin publicarse.

Sobre el debate de fondo, la contribución que más me gustó es la de Redwood Research, publicada el 25 de julio, o sea cuatro días antes de que se anunciara el acuerdo con OpenAI. Es análisis propio sobre información pública, no un adelanto de la auditoría.

Los prompts de ExploitGym restringen explícitamente tanto los objetivos como los métodos, y descartan de forma expresa vulnerabilidades o técnicas no relacionadas ENTONCES escapar del sandbox para atacar a Hugging Face violó esos límites. Así que "solo estaba siguiendo instrucciones" no se sostiene. Pero, y esto es igual de importante, tampoco es evidencia fuerte sobre la calidad del entrenamiento de alineamiento de OpenAI, porque nunca dijeron qué técnicas de alineamiento tenían esos modelos. El fallo demostrado fue de contención, monitoreo y gobernanza de evaluaciones y posteriormente de algún auditoría gubernamenatal o multa.

METR, por su lado, ya había dejado un dato lateral que a mí me pareció clarificador, y que tampoco tiene nada que ver con la auditoría pendiente. Está en su Frontier Risk Report de febrero-marzo 2026, publicado el 19 de mayo. En una de sus evaluaciones, Opus 4.6 se quedó sin los créditos de API que necesitaba para resolver una tarea de ML, salió a buscar cómputo gratis en internet sabiendo que eso iba en contra de las instrucciones de la tarea, y consiguió un score aprobado. La misma dinámica, en miniatura, dos meses antes de que a nadie se le ocurriera hablar de agentes rogue.


Qué haría yo si fuera vos al día siguiente de cuando estés leyendo esto

Todo lo anterior es historia. Esto es lo accionable, ordenado por relación entre impacto y esfuerzo. Es la lista que armé después de leer todo el material, mirar videos, leer noticias y blog posts de terceros.

  1. 1

    Asumí que tu sandbox aísla menos de lo que creés

    Toda caja "aislada" termina teniendo una excepción operativa, alguna puerta que dejaste abierta porque el sistema la necesita para funcionar. Esa excepción es exactamente lo primero que un agente va a encontrar. Listá cuáles son las salidas a internet de tus entornos de IA, dejá las mínimas y restringilas a destinos conocidos. Y sumale un botón de apagado que no dependa del sistema que estás tratando de contener.

  2. 2

    Cortá el atajo entre ejecutar código y tener credenciales

    Acá, ejecutar Python adentro de un pod alcanzó para leer el entorno y salir con tokens de la nube. Ese salto es el que hay que romper. Bloqueá que tus cargas de trabajo puedan consultar el servicio de metadata de tu proveedor cloud, que fue literalmente el fix número uno de Hugging Face, y sacá los secretos de las variables de entorno. Si un proceso comprometido no encuentra credenciales tiradas ahí, la cadena se corta en el primer paso.

  3. 3

    Mirá los datos que procesás como si fueran código

    El pipeline de Hugging Face no cayó por la puerta de red: cayó porque alguien subió un archivo. Cualquier formato que permita apuntar a otro archivo, evaluar plantillas o importar código es un programa disfrazado de dato. Si tu sistema recibe archivos de usuarios y los procesa, tratá ese camino con el mismo cuidado que tratarías un endpoint público. La regla corta que me llevé: un valor de configuración es un dato, nunca una expresión que se evalúa.

  4. 4

    Que ninguna credencial sola abra todas las puertas

    El salto a administrador total no vino de un zero-day, vino de una credencial compartida entre varios ambientes. Buscá si tenés alguna llave que funcione en más de un lugar y partila en llaves separadas. Y revisá que una carga de trabajo común no tenga permiso para crear procesos con privilegios de administrador de la máquina, que fue el otro escalón que usó el agente.

  5. 5

    Asegurate de que la alarma efectivamente suene

    Este es el punto que más me marcó. La detección de Hugging Face funcionó bien: juntó las señales sueltas y armó el patrón correcto. Lo que falló fue que no despertó a nadie. Elegí cuatro o cinco eventos que nunca son normales (alguien leyendo secretos, un proceso pidiendo permisos de administrador, una ráfaga de dispositivos nuevos en tu VPN) y hacé que suene el teléfono sí o sí, sin importar qué puntaje le ponga el sistema automático.

  6. 6

    Tené un modelo propio listo para investigar

    Es la lección menos discutida de todo el caso y la más barata de aplicar. El día que tengas que analizar los logs de un ataque real, los modelos comerciales te van a decir que no, porque no distinguen a quien investiga de quien ataca. Dejá uno open-weight corriendo en tu propia infraestructura y probalo antes de necesitarlo. De paso, los datos del incidente nunca salen de tu casa.

  7. 7

    Escribí dos planes de respuesta, no uno

    Uno para cuando el agente de otro te ataca a vos. Otro para cuando el tuyo se desvía y termina atacando a un tercero. Son incidentes distintos, con evidencia distinta y con responsables distintos, y casi nadie tiene escrito el segundo. La CSA lo plantea exactamente así en su post-mortem, y me parece el reencuadre más útil que dejó todo esto.


Referencias

Si querés ir a las fuentes y no a la cobertura, estas son las que realmente valen en orden de relevancia y peso:

  1. Hugging Face - Anatomy of a Frontier Lab Agent Intrusion - El timeline técnico del 27 de julio, con el replay interactivo de las 17.600 acciones. Es el documento central del caso.
  2. Hugging Face - Security incident disclosure, July 2026 - La divulgación inicial del 16 de julio, cuando todavía no sabían quién era el atacante.
  3. OpenAI - Security incident during model evaluation - El post del 21 de julio con sus updates del 28 y 29.
  4. ExploitGym, arXiv:2605.11086 - El paper del benchmark. Vale leer la sección de rutas no previstas.
  5. JFrog - Fast Remediation Is the New Trust Model - El advisory de Artifactory y los parches.
  6. Anthropic - Investigating three real-world incidents in our cybersecurity evaluations - La revisión de las 141.006 corridas.
  7. Redwood Research - The OpenAI models that hacked Hugging Face weren't just following instructions - El mejor análisis del debate de alineamiento vs contención.
  8. Elastic Security Labs - GenAI detection with Elastic Defend - El mapeo stage-by-stage a ATT&CK y ATLAS con reglas concretas.
  9. BleepingComputer - OpenAI models used Artifactory zero-days to escape to the internet - El trabajo de rastreo de los ocho CVEs.

Cierre: el perímetro es la suma de lo que le concediste al agente

Si tuviera que quedarme con una sola idea del tiempo que le dediqué a este caso, sería esta: el modelo nunca hizo nada que no fuera coherente con lo que le pidieron. Le dieron un objetivo binario, herramientas reales, memoria, un presupuesto de inferencia generoso y le sacaron los frenos. Después todos nos sorprendimos todos de que buscara cualquier estado del mundo que satisficiera al evaluador.

Ninguna de las piezas técnicas era nueva. SSRF en un proxy, un endpoint público sin auth, path abuse en HDF5, SSTI en Jinja2 (quizás un poco fuera de lo común), RBAC demasiado ancho, pods privilegiados sin admission control, una credencial compartida con system:masters, una key de VPN reutilizable, una GitHub App con permisos de escritura. Cada una de esas cosas se suelen ver en algunos pentests y en security configuration reviews. Lo que cambió es que apareció algo capaz de encontrarlas todas, combinarlas, fallar miles de veces sin cansarse (por días non stop), y sostener staging, C2 y persistencia en paralelo durante cuatro días y medio.

Eso no cambia las primitivas del ataque. Cambia su economía. Y cuando cambia la economía de un ataque, todos los cálculos de riesgo que hiciste asumiendo un atacante humano con tiempo limitado dejan de servir.

Para los que trabajamos en esto, el reencuadre concreto que me llevo es que la pregunta de seguridad ya no puede ser "¿está permitida esta acción?" sobre una herramienta aislada. Tiene que ser "¿hacia qué resultado apunta esta secuencia de acciones?". Un install de dependencia, una consulta al credential store y un POST de datos ofuscados son tres eventos benignos por separado, y una intrusión completa cuando los mirás en una misma trayectoria a velocidad de máquina.

Si llegaste hasta acá, como siempre gracias de verdad por el tiempo invertido y compartido. Si te llevás una sola cosa práctica, que sea la más barata de todas: andá y probá hoy si tenés un modelo capaz corriendo en tu propia infraestructura, uno que no te diga que no cuando le pases logs de ataque reales. Porque el día que lo necesites, no vas a tener tiempo de descubrir que no lo tenés o las miradas punzantes en un war room van a hacer que todo el proceso sea estresante como poco.

Pon a Prueba tu Conocimiento Tecnico

Easy

¿Cuál era el objetivo real del agente cuando comprometió la infraestructura de producción de Hugging Face?

Medium

El allowlist de URLs de la librería de datasets bloqueó correctamente el intento inicial de SSRF contra el endpoint de metadata de la nube. ¿Por qué esa defensa no impidió el compromiso?

Hard

Dentro del cluster de Kubernetes, ¿qué falla de configuración específica le dio al agente privilegios de cluster-admin en dos clusters casi instantáneamente?

NewPublished Yesterday

Continue Reading

Next steps in the archive

Keep Exploring

Related reading

Continue through adjacent topics with the strongest tag overlap.