← Todos los insights

Análisis de noticiaEnfoque: España y Latinoamérica5 min de lectura

La versión maliciosa de LiteLLM estaba firmada: lo que una firma no puede probar en un gateway de IA

LiteLLM 1.107.0 distribuyó código que roba credenciales por PyPI y las imágenes oficiales de Docker, firmado por un workflow de release secuestrado. A qué apuntó y qué exige la recuperación.

Escuche este artículo · 7 min

Narración completa del artículo, generada con IA.

Un sello de goma de madera sobre un tampón de tinta abierto, en duotono La Madre, junto a las palabras Firmado no es seguro
Foto: rawpixel (CC0)

Las imágenes envenenadas de LiteLLM estaban firmadas. Un equipo que hubiera verificado cada firma de contenedor antes de desplegar el 21 de octubre las habría aceptado, porque el workflow de release que construyó el malware también lo firmó.

Ese es el detalle que conviene asimilar del compromiso de LiteLLM 1.107.0, el gateway de código abierto que muchas empresas colocan entre sus aplicaciones y todos los proveedores de modelos que usan. El 21 de octubre, de 11:39 a 13:23 UTC, el paquete de PyPI llevó código que roba credenciales; de 11:46 a 14:20 UTC, las etiquetas oficiales de Docker Hub v1.107.0, latest, main-latest y main-stable apuntaron a imágenes comprometidas. Microsoft publicó una investigación técnica el 23 de octubre. LiteLLM rotó su clave de firma el 24 de octubre. LangChain bloqueó la versión en su integración el 25 de octubre.

Cómo los propios logs de un gateway se convirtieron en la vía de entrada

Según los mantenedores de LiteLLM, el atacante usó credenciales de GitHub CLI de desarrolladores, una de ellas de un propietario de la organización, lo que permitió desactivar las protecciones de rama. Ejecutaron el workflow de release del proyecto contra un repositorio de aspecto similar, Berri-AI/litellm en lugar de BerriAI/litellm, y ese workflow construyó y firmó los artefactos. Los tokens, según los mantenedores, presuntamente se tomaron de los logs de un despliegue interno de LiteLLM expuesto, donde las respuestas de una herramienta de programación los habían transportado. Cómo llegó el atacante a ese despliegue sigue sin confirmarse.

Cómo se envenenó la versión 1.107.0 de LiteLLM01Tokensexpuestosen los logsde ungatewayinterno02Credencialesdedesarrolladorreutilizadas,protecciónde ramadesactivada03Workflow dereleaseejecutadocontra unrepositoriode aspectosimilar04Artefactosconstruidosy firmadospor eseworkflow05Publicadosen PyPI,Docker Huby etiquetasde GHCR06El códigose ejecutaal arrancarPython yrecogesecretosLa firma era válidaEl pipeline de confianza hizo el trabajo
  1. Tokens expuestos en los logs de un gateway interno
  2. Credenciales de desarrollador reutilizadas, protección de rama desactivada
  3. Workflow de release ejecutado contra un repositorio de aspecto similar
  4. Artefactos construidos y firmados por ese workflow
  5. Publicados en PyPI, Docker Hub y etiquetas de GHCR
  6. El código se ejecuta al arrancar Python y recoge secretos

La firma era válidaEl pipeline de confianza hizo el trabajo

Basado en la entrada del incidente de LiteLLM y en la investigación de Microsoft del 23 de octubre de 2026. El acceso inicial al despliegue interno no está confirmado.

Lea la cadena desde el final y todos los controles parecen correctos: el paquete vino del índice oficial, la imagen del registro oficial, la firma de la clave oficial. El fallo estaba más arriba, en quién podía ejecutar el pipeline. Una firma prueba qué clave firmó un artefacto. No prueba que las personas correctas, desde la fuente correcta, lo pidieran.

Desinstalar nunca iba a ser suficiente

El análisis de Microsoft explica por qué esta versión fue peor que un paquete malicioso típico. Colocó archivos en el directorio de librerías de Python que se ejecutan cada vez que arranca el intérprete, de modo que el código se ejecutaba sin que nadie importara LiteLLM. Un runner de CI que solo tuviera el paquete instalado, una laptop de desarrollador, un contenedor de pruebas: todos lo ejecutaron. Borrar la carpeta de LiteLLM puede dejar esos archivos de arranque en su sitio.

El recolector fue detrás de lo que suele albergar un host de gateway: credenciales de nube para AWS, Azure y Google Cloud, configuración de Kubernetes y Docker, claves SSH, GPG y de CI/CD, material de Vault, variables de entorno, configuración de herramientas de desarrollo y de IA, incluidas integraciones de MCP, y registros de la base de datos del proxy de LiteLLM, donde viven las claves de los proveedores. Microsoft vio la preparación y las conexiones salientes en los endpoints, pero es cuidadosa con los límites: el arranque por sí solo “no probó que la recolección o la carga se completaran”, una segunda etapa no se confirmó y Microsoft no ha determinado de forma independiente cómo entró el atacante al principio.

La guía del propio LiteLLM es más directa: si 1.107.0 se ejecutó en un host con salida a internet, asuma que los datos salieron. Rote el rol de la instancia, todas las claves de proveedor guardadas en el proxy, las claves maestra y virtuales, y la contraseña de la base de datos. La versión empresarial privada no se vio afectada y las versiones públicas anteriores son seguras; los mantenedores recomiendan fijar 1.106.2 u otra versión explícita anterior al incidente.

Las versiones posteriores cambian su configuración, no su exposición

Dos versiones posteriores merecen atención porque tocan los pipelines de despliegue:

  • 1.106.3 (24 de octubre) firma cada imagen de Docker y cada chart de Helm con una nueva clave de cosign. La verificación contra la clave antigua ahora falla, así que cualquier copia fijada de la clave pública en scripts, comprobaciones de CI o políticas de admisión (Kyverno, Sigstore policy-controller, Connaisseur) tiene que sustituirse. La versión también elimina la CA raíz de eMudhra de los paquetes de confianza. Las notas de la versión no mencionan el incidente, y una clave nueva no vuelve fiable nada que ya esté desplegado.
  • langchain-litellm 0.11.2 (25 de octubre) fija un mínimo de LiteLLM de 1.106.2 y excluye 1.107.0, lo que importa porque muchos equipos nunca eligieron una versión de LiteLLM: la eligió su framework.

Ninguna sustituye a la recuperación. La frase de Microsoft que conviene recordar es: “Eliminar el paquete o una etiqueta de versión no es una recuperación suficiente.”

Qué le pide el incidente a los equipos que operan un gateway

Un gateway de IA está hecho para concentrar cosas: claves de cada proveedor, reglas de enrutamiento, límites de gasto, logs de prompts y respuestas. Hemos sostenido que se está convirtiendo en un punto de control de políticas, y por eso mismo su host merece la protección de una infraestructura de identidad. De este incidente se derivan cuatro prácticas:

  1. Fijar por digest y bloquear por hash. Etiquetas mutables como latest y main-stable estuvieron entre las reasignadas. Un despliegue que referencia un digest de imagen y un archivo de bloqueo con hashes no habría recogido el nuevo artefacto en silencio.
  2. Tratar los logs del gateway como almacenes de secretos. Si las respuestas pueden llevar tokens, los logs heredan su sensibilidad: restrinja el acceso, redacte credenciales y mantenga una retención corta.
  3. Limitar el tráfico de salida desde hosts de compilación, de desarrollo y de gateway. El recolector necesitaba una conexión saliente. La mayoría de estas máquinas necesita una lista de permitidos corta, no internet.
  4. Inventariar dónde se ejecuta realmente el paquete. Las cachés de pip y uv, los mirrors internos, las imágenes base y las dependencias de frameworks son donde una versión fijada se deshace.

La lección incómoda no es que los gateways de código abierto sean inseguros. Es que los controles en los que más equipos confían (fuente oficial, firma válida, editor conocido) pasaron todos, y el ataque funcionó igualmente.

¿Tiene un caso de uso de IA detenido entre el prototipo y la producción?

Cuéntenos qué quiere poner en marcha. Le respondemos con próximos pasos honestos.

Conversemos sobre un caso de uso