🔑 Resumen clave
A través de una vulnerabilidad de dependencia en Trivy se robaron tokens de API, y eso se usó como punto de apoyo para publicar versiones maliciosas de los paquetes litellm y telnyx en PyPI. El código malicioso se ejecutaba inmediatamente después de la instalación, recopilaba credenciales y archivos sensibles, y luego los filtraba a un servidor externo.
⚠️ Por qué este malware es diferente
La mayoría de los paquetes maliciosos previos en PyPI eran paquetes creados desde cero (como en ataques de typosquatting). Este ataque es distinto: consiste en inyectar código malicioso en paquetes de código abierto ya ampliamente usados.
Hay dos rutas de inyección:
- atacar directamente proyectos de código abierto con repositorios, flujos de liberación o autenticación débiles
- robar tokens y claves de API de máquinas de desarrolladores que instalan la versión más reciente
Con los tokens de API de PyPI o GitHub robados, se comprometían adicionalmente otros paquetes de código abierto, formando una estructura de ataque en cadena.
📅 Cronología del incidente
LiteLLM
Durante el período de exposición de la versión maliciosa, se descargó más de 119,000 veces.
PyPI recibió 13 reportes mediante la función de "reporte de malware".
| Etapa | Tiempo transcurrido |
|---|---|
| Subida → primer reporte | 1 hora 19 min |
| Primer reporte → aislamiento | 1 hora 12 min |
| Tiempo total de exposición | 2 horas 32 min |
LiteLLM se instala unas 15 a 20 millones de veces por semana, y unas 1,700 veces por minuto. De esas instalaciones, aproximadamente entre 40% y 50% no fijaban versión, por lo que recibían automáticamente la versión más reciente.
Telnyx
El paquete telnyx fue aislado automáticamente gracias al sistema de trusted reporters de PyPI.
| Etapa | Tiempo transcurrido |
|---|---|
| Subida → primer reporte | 1 hora 45 min |
| Primer reporte → aislamiento | 1 hora 57 min |
| Tiempo total de exposición | 3 horas 42 min |
🛡️ Recomendaciones de seguridad para desarrolladores
1. Cooldowns de dependencias (Dependency Cooldowns)
Es una estrategia para configurar que no se instalen paquetes publicados recientemente durante cierto período, con el fin de dar tiempo a investigadores de seguridad y administradores de PyPI para responder.
uv — actualmente compatible:
# ~/.config/uv/uv.toml o pyproject.toml
[tool.uv]
exclude-newer = "P3D" # excluir paquetes publicados en los últimos 3 días
pip v26.1 — con soporte previsto durante abril:
# ~/.config/pip/pip.conf
[install]
uploaded-prior-to = P3D
⚠️ Un cooldown no es una solución universal. Si se necesita un parche de seguridad, debe instalarse de inmediato, así que conviene usarlo junto con herramientas de escaneo de vulnerabilidades como Dependabot o Renovate.
2. Bloqueo de dependencias (Lock Files)
pip freeze, que solo registra versiones, no es un lock file. Para seguridad, hace falta un lock file real que incluya checksums/hashes.
Herramientas recomendadas:
uv lockpip-compile --generate-hashespipenv
🔒 Recomendaciones de seguridad para mantenedores de código abierto
1. Reforzar la seguridad del flujo de liberación
- No usar triggers inseguros —
pull_request_targetde GitHub Actions es especialmente riesgoso - Sanitizar parámetros y valores de entrada — pásalos como variables de entorno para evitar template injection
- No usar referencias mutables — usar commit SHA en lugar de etiquetas Git y mantener lock files de dependencias
- Configurar despliegues con revisión obligatoria — combinar Trusted Publishers + GitHub Environments para requerir aprobación adicional al publicar
Si usas GitHub Actions, se recomienda revisar vulnerabilidades del workflow con la herramienta Zizmor.
2. Usar Trusted Publishers en lugar de tokens de API
- Los tokens de API tienen larga duración, así que si son robados es difícil detectarlo de inmediato
- Trusted Publishers usa tokens de corta duración, así que incluso si son robados deben usarse de inmediato, lo que reduce el riesgo
- Con Digital Attestations, los usuarios descendentes pueden detectar publicaciones que no pasaron por un flujo de liberación legítimo
3. Aplicar 2FA de forma obligatoria
Desde 2024, PyPI exige 2FA para publicar paquetes. Pero hay que aplicar 2FA (idealmente con llave de hardware) no solo a la cuenta de PyPI, sino a todas las cuentas relacionadas con el desarrollo de código abierto, como GitHub, GitLab y correo electrónico.
💰 Cómo apoyar esta actividad
Las actividades de seguridad de PyPI son posibles gracias al apoyo de la Python Software Foundation (PSF). Se puede participar a través del programa de patrocinio de la PSF, con apoyo directo, o escribiendo a sponsors@python.org.
Los cargos de ingenieros de seguridad de PyPI de Mike Fiedler y Seth Larson cuentan con el apoyo de Alpha-Omega.
1 comentarios
Hice un servidor MCP y lo subí a npm, y la verdad este informe del incidente me pareció bastante inquietante.
Al final, los servidores MCP también se publican tal cual en npm y PyPI, y hay bastantes casos en los que se instalan sin fijar versiones, además de que todavía no existen cosas como un sistema de reportes o
trusted publisher. Si LiteLLM estuvo expuesto apenas un poco más de 2 horas y aun así tuvo esa cantidad de descargas, me dio la impresión de que en este lado, una vez que algo entra, puede quedarse bastante tiempo.También vi que del lado de Claude Code, al hacer
pip installhay casos en los que este tipo de configuraciones de protección no se aplican bien, así que si el flujo es que el agente instala paquetes por su cuenta, no queda muy claro en qué punto habría que bloquearlo.