Una clave maestra de LiteLLM olvidada abrió la puerta a una versión envenenada en PyPI
Un único secreto publicado en un repositorio público, y nunca revocado, permitió a un atacante llegar hasta el pipeline de publicación de LiteLLM. El 21 de octubre de 2026 apareció en PyPI una versión maliciosa, LiteLLM 1.107.0, junto con imágenes en Docker Hub y GHCR. Quedó en cuarentena en unas dos horas, pero quien la haya instalado en ese intervalo debe dar por comprometido el equipo.
Qué ocurrió
La cadena de hechos comenzó meses antes:
- 27 de mayo de 2026 – Un archivo de configuración subido a un repositorio público de LiteLLM incluía la clave maestra de un despliegue interno de su Agent Platform. El commit se sobrescribió rápidamente con un force-push y las claves expuestas se marcaron para revocar, pero la clave maestra nunca se revocó.
- 10 de octubre de 2026 – Un actor desconocido usó esa clave, todavía válida, para entrar en Agent Platform y extrajo un token OAuth de GitHub CLI que el servicio usaba para abrir pull requests. El token no tenía permisos restringidos y pertenecía al propietario de la organización de GitHub, lo que dio al atacante acceso de nivel owner a todos los repositorios.
- 10 y 12 de octubre – El atacante subió commits a ramas efímeras (con el patrón
ci-tmp-<hex>), cada uno con un workflow en.github/workflows/cache.ymly el inocente mensaje "ci: bump cache config". Los workflows se ejecutaban al hacer push y las ramas se borraban minutos después, sin dejar apenas rastro en el historial habitual. Así obtuvo los tokens de GitHub CLI de dos ingenieros con permisos de maintainer y una larga lista de otros secretos. - 21 de octubre de 2026 – El atacante se saltó la protección de rama, apuntó el pipeline de publicación a un repositorio con un nombre casi idéntico (
Berri-AI/litellmen lugar deBerriAI/litellm), publicó la versión 1.107.0 en PyPI, subió las imágenes de contenedor y después borró los registros de ejecución de producción y staging. - El incidente se notificó ese mismo día; PyPI puso la versión en cuarentena y las etiquetas de Docker afectadas (
v1.107.0,latest,main-latest,main-stable) se eliminaron o se redirigieron a imágenes limpias.
Normalmente, una publicación debe iniciarla un ingeniero autorizado y aprobarla una cuenta especial vinculada a un dispositivo físico en la oficina. Ese control se había relajado días antes para que dos ingenieros cualesquiera pudieran iniciar y aprobar una publicación, con el fin de agilizar los backports de correcciones. Con dos tokens de maintainer robados, el atacante pudo hacer ambas cosas. Cabe destacar que, con un token de owner, el atacante podría haber eliminado la restricción por completo; una explicación plausible es que no lo hizo para no llamar la atención.
Qué se llevaron los workflows maliciosos
Los workflows de CI estaban diseñados para recolectar credenciales, no código. Entre los secretos buscados: tokens de GitHub, el identificador y la clave privada de firma de una GitHub App, claves del espacio de trabajo de Linear, del despliegue de LiteLLM y de Together AI y, en la segunda ejecución, claves API de Anthropic, OpenAI, AWS Bedrock y Tavily, el token del servicio de detección de secretos del propio proyecto, datos de conexión de PostgreSQL y Redis, y una sesión de navegador de Playwright serializada para Linear. Este último punto es clave: un estado de sesión válido permite entrar en la cuenta asociada sin contraseña y sin MFA. Robar el token de detección de secretos también podía dar al atacante visibilidad sobre las alertas pensadas para detectar justo esta actividad, o incluso control sobre ellas.
LiteLLM afirma que está revocando todos los tokens asociados a sus sistemas internos y plataformas de proveedores. También reconoció que su primera hipótesis, que los tokens de GitHub se habían filtrado desde los registros de un despliegue interno, resultó ser errónea.
Qué hace el paquete envenenado
La versión 1.107.0 coloca archivos de arranque de Python (.pth y sitecustomize.py) fuera del directorio del paquete LiteLLM. Como Python los carga automáticamente, el código malicioso se ejecuta cada vez que arranca el intérprete en ese entorno, aunque ninguna aplicación importe LiteLLM. A partir de ahí tiene dos vías:
- Ladrón de credenciales – recopila credenciales de herramientas de desarrollo y de IA, secretos de nube y de cargas de trabajo, datos de navegador, claves SSH, tokens de Git y GitLab, variables de entorno y tokens de npm, PyPI, pip, Yarn, Maven, Gradle, Composer, RubyGems y Cargo. Los datos se cifran (AES-256-CBC con la clave protegida mediante RSA-OAEP) y se envían por HTTP POST a
litellm[.]dev/healthcheck, un dominio de imitación registrado el 13 de octubre de 2026. - Puerta trasera para Unix – un proceso persistente que consulta aproximadamente cada hora si hay código del atacante para descargar y ejecutar. La capacidad se identificó en el código, pero no se ha confirmado que la ejecución remota llegara a producirse.
Como los archivos de arranque están fuera de la carpeta de la aplicación, desinstalar o actualizar LiteLLM puede no eliminar los componentes maliciosos.
Por qué importa
Por separado parecen menores. Juntas, permitieron al atacante distribuir código a todos los que confían en un gateway de IA muy popular. Los equipos de desarrollo y los runners de CI, que guardan las llaves de la nube, los registros de paquetes y los proveedores de IA, son el verdadero objetivo.
Qué hacer
- Compruebe si usa la 1.107.0. Busque
litellm==1.107.0en lockfiles, entornos virtuales, imágenes de contenedor y cachés de CI, así como imágenes descargadas de las etiquetas afectadas el 21 de octubre de 2026. - Reconstruya, no se limite a actualizar. En cualquier máquina o imagen afectada, busque archivos
.pthinesperados ysitecustomize.pyen site-packages. Lo más seguro es reconstruir el entorno o el equipo desde un estado de confianza. - Rote todo lo que ese entorno pudiera alcanzar: claves de nube, claves API de proveedores de IA, tokens de GitHub y GitLab, tokens de registros de paquetes, claves SSH, contraseñas de bases de datos y sesiones de navegador. Asuma que fueron robados.
- Busque indicadores de compromiso: tráfico hacia
litellm[.]devowebhook[.]sitey desde69.48.229[.]143; procesos de Python persistentes que se ejecutan cada hora sin explicación. - Revise la higiene de su propio pipeline. Limite los tokens de CI y de bots al mínimo imprescindible, revoque de inmediato los secretos filtrados (reescribir el historial de git no revoca nada), mantenga las aprobaciones de publicación vinculadas a cuentas con llave física y configure alertas para ramas efímeras que añadan o modifiquen workflows.
Los secretos subidos a repositorios y los workflows de CI con permisos excesivos son justo lo que busca nuestra revisión de código asistida por IA. Analiza el código fuente, la configuración y las definiciones de pipeline en busca de credenciales incrustadas y automatizaciones de riesgo antes de que se conviertan en el primer eslabón de una cadena como esta.
