← Todos los articulos

La bomba fork nos salvó

El malware de LiteLLM 1.82.8 incluía un archivo .pth que se ejecutaba en cualquier arranque de Python. Recolectaba claves SSH, credenciales de nube, billeteras de criptomonedas y secretos de CI/CD; los cifraba con una clave RSA de 4096 bits y exfiltraba el archivo comprimido hacia un dominio controlado por el atacante. La carga útil estaba bien construida. El cifrado era sólido. La exfiltración, limpia.1 Este incidente forma parte de mi serie sobre seguridad de agentes, dedicada a las fallas reales que moldean la forma en que construimos confianza en los sistemas automatizados.5

El archivo .pth también generaba un proceso hijo de Python para hacer su trabajo. Ese proceso hijo disparaba de nuevo el archivo .pth. Lo que generaba otro proceso hijo. Que lo disparaba otra vez. Una bomba fork exponencial que consumía el 100 % de la CPU y más de 5 GB de RAM en cuestión de segundos.2

La bomba fork era un error. El atacante no quería que el malware fuera visible. Una versión bien implementada habría corrido en silencio en cada invocación de Python en cada sistema infectado, quizá durante semanas. En cambio, los desarrolladores notaron que sus máquinas se arrastraban hasta detenerse, investigaron y encontraron el ladrón de credenciales. PyPI puso ambas versiones en cuarentena 46 minutos después de su publicación.1

Cuarenta y seis mil instalaciones en cuarenta y seis minutos. El mecanismo de detección fue un error de implementación en el malware.

Cuando una dependencia de un agente de IA instala un paquete que contiene una bomba fork, la generación exponencial de procesos consume el 100 % de la CPU y varios gigabytes de RAM en segundos, y deja la máquina inutilizable. En el incidente de LiteLLM 1.82.8, esa bomba fork accidental fue la única razón por la que se detectó una carga útil que robaba credenciales: los desarrolladores notaron que sus máquinas se arrastraban hasta detenerse e investigaron. Sin el error, el malware habría exfiltrado en silencio claves SSH, credenciales de nube y billeteras cripto durante semanas antes de que alguien lo descubriera.

En resumen

  • El error: el ladrón de credenciales de LiteLLM 1.82.8 tenía una bomba fork que dejaba las máquinas infectadas al borde de la parálisis. Sin ese error, habría funcionado en silencio durante semanas.
  • La brecha: el análisis estático, el monitoreo de comportamiento y la revisión de código dejaron pasar el ataque. Cada capa de detección dio por sentado que otra capa lo atraparía. Ninguna lo hizo.3
  • La curva: la calidad de los atacantes mejora con cada iteración. La técnica del .pth ya está documentada públicamente. El próximo atacante la hereda sin el error.
  • Lo que funciona sin depender de la suerte: verificar la antigüedad del dominio en las salidas de red, establecer líneas base de comportamiento para la instalación de paquetes, sembrar señuelos en el sistema de archivos y aislar la instalación. Cada medida funciona sin importar la calidad de la carga útil.
  • La asimetría: quien defiende elige el entorno. Si el entorno de instalación no tiene credenciales que robar, una carga útil perfecta no cosecha nada.

Tuvimos suerte

Quítale la bomba fork a la carga útil y el ataque tiene éxito en silencio. El archivo .pth se ejecuta antes de cualquier import, antes de cualquier código de aplicación, antes de cualquier entorno aislado a nivel de Python. No hay punto de enganche. No hay entrada de registro. El ladrón de credenciales corre, cifra, exfiltra, y el proceso de Python sigue como si nada. El desarrollador no ve nada. El pipeline de CI no ve nada. El escáner de seguridad no ve nada, porque el escáner de seguridad era, para empezar, el vector de ataque.3

La historia de la detección de LiteLLM 1.82.8 no es «nuestro monitoreo lo atrapó». La historia es «el atacante publicó un error».

No es una base cómoda para la seguridad de la cadena de suministro. Como sostengo en tu entorno aislado de agentes es apenas una sugerencia, los límites que suponemos que existen entre el código confiable y el que no lo es resultan mucho más porosos de lo que la mayoría de los equipos imagina.

La curva de calidad del atacante

La calidad del software mejora con la iteración, y eso vale tanto para quien ataca como para quien defiende. La campaña de TeamPCP golpeó cinco ecosistemas en una sola semana: GitHub Actions, Docker Hub, npm, Open VSX y PyPI.4 Cada ecosistema comprometido se abrió con credenciales cosechadas del anterior. La campaña demostró un nivel de sofisticación operativa notable: registro del dominio 24 horas antes de la entrega de la carga útil, secuestro de etiquetas sobre referencias mutables y evasión de la rotación de credenciales aprovechando que Aqua Security cambió sus claves de forma incompleta.

La bomba fork fue el único error en una operación por lo demás competente. La próxima campaña no lo cometerá. La técnica del archivo .pth ya está documentada públicamente y analizada por CrowdStrike, Microsoft, Wiz y Palo Alto.3 El próximo atacante hereda la técnica sin el error.

La capacidad adversaria sigue la misma curva de mejora que la capacidad defensiva. La técnica es pública. El análisis es público. El próximo atacante arranca donde TeamPCP terminó. Exploro lo que significa esta curva para los sistemas autónomos en qué se rompe de verdad sin supervisión.

La detección no puede depender de los errores del atacante

El modelo actual de detección en la cadena de suministro tiene tres capas, y las tres fallaron con LiteLLM:

El análisis estático no lo vio. El archivo .pth es una función legítima de Python. La carga útil venía codificada dos veces en base64 y se decodificaba en tiempo de ejecución. Los escáneres estáticos que buscan patrones maliciosos conocidos no encuentran nada, porque el patrón es nuevo.

El monitoreo de comportamiento no lo vio. El ladrón de credenciales hizo un único POST HTTPS saliente hacia un dominio que parecía un servicio legítimo (models.litellm.cloud). Un monitoreo de salida que inspeccione dominios de destino tendría que saber que ese dominio específico se había registrado 24 horas antes, y la mayoría no verifica la antigüedad del dominio.

La revisión de código no lo vio. Las versiones maliciosas se publicaron directamente en PyPI, saltándose por completo el pipeline de CI/CD de GitHub. No hubo pull request que revisar. No hubo diff que inspeccionar. El atacante usó credenciales de publicación robadas para subir paquetes ya compilados.

Cada capa de detección dio por sentado que otra parte de la cadena del ataque detectaría el problema. Ninguna lo hizo. Lo detectó la bomba fork.

Qué detecta de verdad al malware silencioso

Si no puedes apoyarte en los errores del atacante, necesitas mecanismos de detección que funcionen sin importar la calidad de la implementación.

Verificar la antigüedad del dominio en las solicitudes salientes. El dominio de exfiltración se registró 24 horas antes del ataque. Una regla de firewall que marque las solicitudes salientes hacia dominios con menos de 7 días de antigüedad lo habría detectado. La regla es simple, la tasa de falsos positivos es manejable y detecta el patrón de exfiltración más común.

Líneas base de comportamiento para los procesos de Python. Un pip install que de pronto empieza a hacer solicitudes POST HTTPS hacia un dominio desconocido es una anomalía. Un monitoreo de comportamiento a nivel de proceso que siga la actividad de red durante la instalación de paquetes lo marcaría.

Señuelos en el sistema de archivos. Coloca una clave SSH falsa en una ruta señuelo y una credencial de AWS falsa en otra. Vigila cualquier proceso que lea esos archivos. Un ladrón de credenciales que barre las rutas estándar leerá los señuelos; un proceso legítimo no. El señuelo dispara la alerta antes de que la exfiltración termine.

Aislamiento de la instalación. Ejecuta pip install en un entorno sin acceso a credenciales reales y copia después los paquetes instalados al entorno de producción. El archivo .pth se dispara durante el propio proceso de Python que ejecuta pip, lo que significa que el ladrón de credenciales corre durante la instalación. Si el entorno de instalación no tiene credenciales que robar, el ataque no cosecha nada.

Ninguno de estos mecanismos exige que el atacante cometa un error: funcionan sin importar la calidad de la carga útil. El patrón arquitectónico —diseñar entornos donde incluso un ataque perfecto no cosecha nada— responde al mismo principio que está detrás de desplegar y defender: la paradoja de la confianza en los agentes.

La asimetría

La defensa tiene una ventaja estructural: quien defiende elige el entorno. Quien ataca debe arreglárselas con el entorno donde se instale el paquete. Si ese entorno no tiene credenciales ni acceso a la red y sí tiene señuelos en el sistema de archivos, la carga útil tiene éxito técnicamente pero fracasa en la práctica.

El ataque a LiteLLM funcionó porque el entorno de instalación era el mismo que guardaba las credenciales de publicación, las claves SSH y los tokens de nube. La bomba fork fue irrelevante para la arquitectura de seguridad; fue relevante para los tiempos.

La próxima vez la bomba fork no estará ahí. Las credenciales seguirán en el mismo entorno que el gestor de paquetes. La pregunta es si habrás cambiado ese entorno antes de que el próximo atacante publique una carga útil impecable. Mi análisis de la arquitectura de agentes Ralph muestra cómo estructurar sistemas de agentes para que los componentes comprometidos no puedan escalar más allá de su frontera de aislamiento.


Preguntas frecuentes

¿Por qué el atacante no probó la bomba fork?

Que el archivo .pth genere un proceso hijo es una decisión de implementación razonable para ejecutar una carga útil sin bloquear el proceso padre. El disparo recursivo es una interacción sutil entre .pth y la inicialización de site.py en Python. Es la clase de error que aparece en las pruebas de integración pero no en las unitarias, y quienes escriben malware tienen pocas oportunidades de hacer pruebas de integración en entornos realistas.

¿Pudo haber sido intencional la bomba fork?

Es poco probable. La bomba fork hizo que el malware fuera visible de inmediato, justo lo contrario del objetivo del atacante. Un ladrón de credenciales silencioso que corre durante semanas cosecha órdenes de magnitud más credenciales que uno detectado en 46 minutos.

¿Es práctico verificar la antigüedad del dominio a gran escala?

Sí. La antigüedad del dominio está disponible por WHOIS o por APIs de fecha de registro DNS. La verificación añade milisegundos de latencia por solicitud, y la mayoría de las organizaciones puede poner en lista blanca los dominios nuevos que ya conoce.


Fuentes


  1. FutureSearch (Daniel Hnyk), “LiteLLM Hack: Were You One of the 47,000?” marzo de 2026. 

  2. isfinne et al., “LiteLLM Supply Chain Attack,” GitHub Issue #24512, marzo de 2026. 

  3. Blake Crosley, “The Supply Chain Is the Attack Surface,” blakecrosley.com, marzo de 2026. 

  4. Kaspersky, “Trojanization of Trivy, Checkmarx, and LiteLLM Solutions,” marzo de 2026. 

  5. Blake Crosley, “When Your Agent Becomes the Researcher,” blakecrosley.com, marzo de 2026. 

Artículos relacionados

Tu agente tiene un intermediario que no verificaste

Se probaron 28 routers de API de LLM de pago: 17 tocaron credenciales canary de AWS y uno drenó ETH. La capa router es l…

14 min de lectura

Ataques a la cadena de suministro de IA: la cadena de suministro es la superficie

Trivy cayó por secuestro de etiquetas, luego LiteLLM en PyPI: 47.000 instalaciones en 46 minutos. La cadena de suministr…

16 min de lectura

El Bucle Ralph: Cómo ejecuto agentes de IA autónomos durante la noche

Construí agentes autónomos con stop hooks, presupuestos de generación y memoria en archivos. Los fracasos y lo que produ…

10 min de lectura