El 21 de octubre a las 11:39 UTC se subieron siete paquetes de litellm==1.107.0 a PyPI. Cada uno llevaba malware compilado: un ladrón de credenciales que además descargaba y cargaba herramientas de ejecución remota de código. Ocho minutos después, las etiquetas de Docker y GHCR latest, main-latest y main-stable apuntaban a la misma compilación envenenada.
A las 13:23 el paquete ya estaba retirado. A las 14:20 las etiquetas de contenedor se habían reasignado.
Dos horas. Suficiente para que un runner de CI lo instalara, un portátil lo importara y unas cuantas claves de API salieran del edificio.
Si construyes algo con IA, este es tu stack ahora. No es una metáfora ni la historia de otro sector. LiteLLM es el proxy que muchos equipos ponen delante de OpenAI, Anthropic y Bedrock para tener una sola API, una sola clave y una sola factura. Cuando se compromete, el compromiso hereda todas las claves de proveedor que guardaste dentro.
La parte que todos van a saltarse
El fallo interesante no es el malware. Es cómo se firmó la versión.
LiteLLM pasó el año siguiente a su incidente de marzo endureciendo el pipeline: publicaciones desde un repositorio privado, Trusted GitHub Publishers, etiquetas inmutables, imágenes firmadas y un portátil de publicación encerrado en la oficina. Según su propio relato, el atacante no rompió ninguno de esos controles. Usó credenciales que ya estaban autorizadas a operarlos:
- Un token OAuth de la CLI de GitHub de un desarrollador, con permiso para ejecutar flujos de trabajo.
- Un token de un propietario de la organización de GitHub, capaz de anular la protección de ramas y forzar un cambio en el flujo de publicación.
- Las credenciales de una tercera cuenta, usadas después de publicar para borrar los registros de ejecución.
¿De dónde salió el primer token? De un log.
La investigación de LiteLLM encontró que Claude Code a veces inserta el token OAuth de la CLI de GitHub del usuario dentro del cuerpo de una respuesta. Su proxy registraba los cuerpos de las respuestas. El token acabó en el log de un despliegue interno de LiteLLM expuesto a internet. Un atacante con una cuenta en ese despliegue leyó los logs, tomó el token y entró al pipeline de publicación.
Lee la cadena otra vez. Nadie hizo phishing. Nadie descifró una contraseña. Un asistente de código que muchos equipos usan hoy puso una credencial viva en una respuesta donde nunca debía estar, la capa de observabilidad la escribió en disco y el disco era accesible.
Por qué esto no es un problema de LiteLLM
El patrón se generaliza a cualquier stack de IA de una empresa normal esta semana:
- Los tokens viajan por el contexto del modelo. Los agentes pegan cabeceras, variables de entorno y salidas de CLI en las respuestas. Todo lo que está en una respuesta se puede registrar, cachear, trazar o evaluar.
- Los proxies agregan credenciales. Una puerta de enlace de IA guarda las claves de cada proveedor al que enruta. Funcionalmente, es un gestor de secretos con superficie HTTP.
- Los agentes heredan la identidad del desarrollador. Si tu asistente corre con tu sesión de
ghy tus permisos de repositorio, un token robado no es "un token", eres tú. - Los despliegues en la sombra no tienen dueño. Una "cuenta de usuario con nombre inofensivo" en un despliegue interno expuesto a internet es el hallazgo más común del mundo, y el más caro.
La misma semana trajo una segunda advertencia independiente. Railway reveló que un tercero no autorizado pudo haber accedido a variables de entorno cifradas y, en algunos casos, obtener su contenido descifrado, y dijo creer que la campaña apuntaba a empresas de plataforma para llegar a proveedores de inferencia de IA. Pidió a todos sus clientes rotar todas las claves.
Dos proveedores, una semana, la misma clase de activo: credenciales que viven junto a la infraestructura de IA.
Los cuatro controles que habrían roto esta cadena
Nada de esto es exótico. Cada eslabón muere con algo aburrido.
1. Trata los logs como superficie de credenciales. Redacta al escribir, no al leer. Si un cuerpo de respuesta puede contener un token de portador, un token OAuth o una cadena de conexión, el logger debe filtrarlo antes de que llegue al almacenamiento. Mantén retención corta para todo lo que guarde prompts y respuestas, y considera cualquier almacén de logs que haya tenido tokens como un evento de rotación.
2. Separa "publicar" de "anular". La barrera de publicación existía y funcionaba. Lo que falló fue que el mismo tipo de identidad podía desactivarla. Una protección de ramas que un propietario de la organización puede desactivar con un token es una sugerencia con auditoría. La autoridad de publicación debe estar detrás de credenciales de corta vida ligadas a hardware y una segunda persona, y nada más debería poder editar el flujo que las usa.
3. Fija y luego demuestra. pip install litellm sin versión es la instrucción de ejecutar lo último que internet publicó. Fija versiones exactas y digests de imágenes. Y ve más lejos: un lockfile es una promesa, no una prueba. Genera un SBOM, verifica firmas donde existan y compara qué hace realmente una versión nueva en tu entorno.
4. Asume la exposición, para que la respuesta sea una lista y no un debate. La guía del propio LiteLLM es el modelo: si lo instalaste, trata el entorno como comprometido. Borra los archivos dropper, mata el demonio que sostiene /tmp/remote_code_loader.lock, rota el rol de instancia, cada clave de proveedor en la base del proxy, las claves maestra y virtuales, y el DATABASE_URL. Después revisa CloudTrail buscando GetCallerIdentity desde el rol de instancia a la hora de la instalación, y el uso de esas credenciales desde fuera de tu infraestructura.
Qué hacer esta semana
Si operas un proxy LiteLLM, haz esto antes del lunes:
pip show litellmen cada host, imagen y runner de CI. Cualquier 1.107.0 está comprometido, no "posiblemente comprometido".- Busca en el sistema de archivos
litellm-1.107.0.dist-info,cook.pthysitecustomize.py. La ausencia no prueba nada; la presencia confirma la exposición. - Rota las claves de proveedor, las claves maestra y virtuales, la contraseña de la base de datos y el rol de instancia en la nube.
- Si usas Railway, rota tus variables de entorno y credenciales de registro privado.
- Audita quién puede editar tus flujos de publicación y elimina los tokens de propietario de organización de cualquier automatización.
Si prefieres que alguien recorra el stack contigo, este es el tipo de trabajo que hacemos como proyecto cerrado: inventario de credenciales, rotación y los controles de pipeline que detienen el siguiente. Escríbenos a [email protected].
La conclusión incómoda
La historia cómoda es que un proveedor tuvo una mala semana. La historia exacta es que el stack de IA moderno compone tres cosas que nunca se diseñaron para estar juntas: un modelo que repetirá encantado cualquier token de su contexto, un proxy que guarda las claves de todo y herramientas de publicación que confían más en una credencial que en una persona.
La ventana del malware fue de dos horas. El rastro de credenciales que dejó la sobrevivirá. Arregla el rastro.