🔥 Paquete LiteLLM comprometido. Si trabajas con APIs de LLM, es hora de preocuparse.

Ayer ocurrió un ataque ejemplar a la cadena de suministro en el ecosistema Python. El paquete litellm fue comprometido: una biblioteca con 97 millones de descargas al mes que ahora está bajo el capó de muchos proyectos de IA.

La versión infectada 1.82.8 llegó a PyPI. Contenía un archivo litellm_init.pth con una carga útil en base64 que hacía una cosa simple: rastreaba tu máquina en busca de secretos y los enviaba a un servidor remoto, replicándose a sí misma.

La lista de lo "robado" incluía todo lo que el script pudo alcanzar:
▫️ Claves SSH
▫️ Credenciales de AWS/GCP/Azure
▫️ Configuraciones de Kubernetes
▫️ Archivos .env (hola, tus tokens de OpenAI)
▫️ Historial del terminal y contraseñas de BD
▫️ Claves SSL privadas y billeteras de criptomonedas

Además, no era necesario escribir pip install litellm para entregar tus claves de producción. Bastaba con instalar o actualizar cualquier herramienta que lo arrastrara como dependencia transitiva. Por ejemplo, actualizar el popular dspy (que tiene litellm>=1.64.0 en sus requirements) — bienvenido al club de los comprometidos.

Pero hay un detalle increíble en toda esta historia.

Lo que salvó a la industria de una catástrofe global fue que el hacker resultó ser un mal programador. 🤡
El malware estaba tan mal escrito que causaba fugas de memoria. Un tipo usó un plugin en Cursor que en segundo plano actualizó litellm. El script consumió toda la RAM y colgó el sistema. Gracias a esto, la versión infectada estuvo en PyPI menos de una hora antes de ser eliminada.

Si el atacante hubiera probado bien su código, el exploit podría haber estado semanas. La mitad de las startups de IA habrían cerrado mañana debido a bases de clientes filtradas y presupuestos agotados en la nube.

Andréi Karpathy opinó al respecto aquí: el paradigma clásico de desarrollo "construimos pirámides con ladrillos de dependencias" se convierte en una vulnerabilidad fatal en la realidad actual. Durante décadas nos enseñaron el patrón académico: "no reinventes la rueda, reutiliza, toma una biblioteca ya hecha".
En la realidad moderna de las cadenas de suministro, esto es como jugar a la ruleta rusa. Cada vez que agregas una nueva dependencia a tu proyecto, arrastras todo su árbol hasta el décimo nivel. Y en algún lugar puede haber un mantenedor ofendido o una cuenta comprometida.

El paradigma está cambiando. En lugar de arrastrar una biblioteca enorme para un par de funciones utilitarias, ahora es más seguro y pragmático simplemente copiar y pegar (o generar con LLM) el fragmento de código necesario y bloquearlo en tu repositorio. 🤷‍♂️