La versión litellm 1.107.0, publicada en PyPI el 21 de octubre, incluía un robador de credenciales y un cargador de código remoto. También estaban infectadas las imágenes Docker de esa versión, y durante unas tres horas las etiquetas latest, main-latest y main-stable apuntaron a ellas.
El paquete ya fue retirado. La versión segura es la 1.106.2. Quien haya instalado la 1.107.0 tiene que tratar ese entorno como comprometido y rotar todas las credenciales que podía leer.
Qué es LiteLLM y por qué importa
LiteLLM es una librería de Python y un proxy que unifica el acceso a distintos proveedores de modelos de lenguaje (OpenAI, Anthropic, Google, Azure y modelos propios) con una misma interfaz. Se usa como gateway de IA: centraliza las API keys, los presupuestos y el registro de consumo.
Según Socket, el paquete tiene unos 23 millones de descargas semanales, y muchas instalaciones llegan como dependencia de otras herramientas de agentes.
Qué pasó
Según la cronología de StepSecurity (horarios UTC del 21 de octubre):
- 08:56 a 10:46: el atacante subió diez commits a un repositorio de nombre casi idéntico,
Berri-AI/litellm(con guion), en lugar del legítimoBerriAI/litellm. - 10:51: arrancó el flujo de publicación oficial del proyecto, construyendo desde ese repositorio falso.
- 11:39: la versión 1.107.0 llegó a PyPI. Minutos después, las imágenes Docker y la release en GitHub.
- 12:06: se reportó el compromiso en el issue #47826 del proyecto.
- Antes de las 13:23: PyPI retiró la versión. Las imágenes infectadas se eliminaron después.
Según el desarrollador de LiteLLM citado por Wiz, el atacante usó tokens OAuth robados de GitHub CLI: con la cuenta de un ingeniero disparó la publicación y con la de otro la aprobó. Los tokens fueron revocados. La etiqueta v1.107.0 del repositorio legítimo no está afectada.
Es el segundo compromiso del paquete en el año: en marzo, las versiones 1.82.7 y 1.82.8 también se publicaron con un robador de credenciales.
Qué hace el código malicioso
Los siete wheels de la 1.107.0 agregan tres archivos a site-packages: cook.pth, cook.py y sitecustomize.py. Python ejecuta los archivos .pth en cada arranque, así que no hace falta importar litellm: alcanza con correr cualquier script o el propio pip en ese entorno.
El robador recolecta, entre otras cosas:
- Credenciales de AWS, Azure, GCP, Kubernetes y Vault, incluidas las de metadatos de instancia.
- Claves SSH, GPG y TLS, y secretos de CI/CD (Jenkins, GitLab Runner y otros).
- Contraseñas, cookies e historial de navegadores, y variables de entorno de los procesos accesibles.
- La configuración de más de 20 herramientas de IA para programar (por ejemplo
~/.claude/.credentials.jsony~/.codex/auth.json). - Si existe
DATABASE_URL, las API keys de los proveedores guardadas en la base del proxy de LiteLLM.
Los datos se cifran y se envían a www.litellm.dev, un dominio registrado el 13 de octubre. En Linux y macOS, además, queda un proceso que cada hora lee una dirección desde un repositorio de GitHub del atacante, descarga código de la ruta /codepy y lo ejecuta.
Según StepSecurity, ese archivo estaba vacío al momento de la publicación, por lo que la segunda etapa no llegó a activarse. Pero los equipos infectados siguen consultando, y el riesgo persiste mientras el proceso esté corriendo.
Qué conviene hacer
- Buscar la versión: revisar lockfiles, caches, logs de build y capas de contenedores en busca de
litellm==1.107.0o de imágenes descargadas conlatest,main-latestomain-stableel 21 de octubre. - Cortar el proceso y reconstruir: detener el proceso que tiene
/tmp/remote_code_loader.lock, borrar los tres archivos e instalarlitellm==1.106.2. Los contenedores se reemplazan, no se limpian en el lugar, fijando la imagenv1.106.2por digest. - Rotar credenciales desde un equipo limpio: nube, SSH, GPG, CI, registros de paquetes, Kubernetes, Vault y herramientas de IA. En los proxies de LiteLLM, también las API keys de los proveedores, la master key y la salt key.
- Bloquear y auditar: bloquear
litellm.deven DNS o en la salida a Internet y buscar en los logs pedidos a ese dominio o a rutas terminadas en/codepy. Un pedido a/codepysignifica que se ejecutó código del atacante.
Para próximos incidentes, una medida que habría evitado este: no instalar versiones recién publicadas. La 1.107.0 estuvo menos de dos horas en PyPI, y uv (exclude-newer), pip (--uploaded-prior-to) y pnpm (minimumReleaseAge) ya permiten fijar ese período de espera.
No es la primera vez que LiteLLM aparece en un incidente este mes: la botnet PoeLLM ya apuntaba a servidores de LiteLLM expuestos a Internet.
¿Saben dónde guardan las keys de sus modelos?
Los gateways de IA concentran las credenciales de todos los proveedores en un solo lugar.
¿Ya revisaron qué versión corre el suyo y qué otras credenciales conviven en esa máquina? Te leemos en los comentarios.
Fuentes
- BerriAI/litellm: [SECURITY] litellm 1.107.0 compromised (issue #47826)
- StepSecurity: litellm 1.107.0 Compromised on PyPI
- Socket: LiteLLM PyPI Package and Docker Images Compromised to Steal Cloud and AI Credentials
- Wiz: LiteLLM Compromised, Steals Credentials
- The Hacker News: LiteLLM compromised in supply chain attack


