El gusano Shai-Hulud explotó CI/CD para comprometer 172 paquetes npm/PyPI, robando credenciales y configuraciones de IA. A pesar de la proveniencia SLSA, el ataque demuestra la urgencia de reevaluar las defensas, aislar sistemas y auditar cadenas de confianza.
Puntos Clave
- 01.La proveniencia SLSA Build Level 3 no es suficiente: el gusano Shai-Hulud comprometió 84 paquetes npm con atestaciones válidas. Es crucial un análisis de comportamiento en tiempo de instalación.
- 02.Las configuraciones de CI/CD de OIDC son un objetivo clave: los atacantes explotaron permisos laxos y envenenamiento de caché para extraer tokens OIDC, eludiendo 2FA y proveniencia.
- 03.El gusano se extiende a Python: el paquete PyPI <code>mistralai v2.4.6</code> ejecuta código malicioso en tiempo de importación, no en instalación, haciendo ineficaces las mitigaciones típicas de npm.
- 04.Los agentes de IA son nuevos objetivos de credenciales: el gusano cosecha configuraciones de Claude y Kiro AI, tratando estos entornos como puntos de confianza para el robo de API keys y tokens.
- 05.El gusano destruye datos si se revoca el token: un daemon persistente borra el directorio de inicio del usuario al detectar la revocación del token npm. Aísle la máquina antes de rotar credenciales.
En un crudo recordatorio de que incluso las certificaciones de seguridad más robustas pueden ser eludidas, un reciente ataque a la cadena de suministro que involucró al gusano 'Mini Shai-Hulud' expuso vulnerabilidades críticas en los modernos pipelines de CI/CD. Esta sofisticada campaña, que afectó a 84 versiones maliciosas en 42 paquetes npm de @tanstack/* —todos ellos con atestaciones de proveniencia SLSA Build Level 3 válidas— logró evadir los mecanismos de confianza establecidos. La proveniencia, una piedra angular de la seguridad de la cadena de suministro de software, no detectó ninguno de estos paquetes envenenados. Este incidente, que impactó a millones de descargas y se extendió de npm a PyPI, exige una reevaluación urgente de nuestras estrategias de defensa, especialmente dado que el gusano ataca activamente las configuraciones de agentes de IA e implementa mecanismos destructivos de persistencia.
El 11 de mayo, entre las 19:20 y las 19:26 UTC, el gusano 'Mini Shai-Hulud' publicó 84 versiones maliciosas en los paquetes npm de @tanstack/*. En menos de 48 horas, la campaña se expandió a 172 paquetes y 403 versiones maliciosas en npm y PyPI, afectando a populares bibliotecas como @tanstack/react-router, que recibe 12.7 millones de descargas semanales. Este ataque sin precedentes, identificado con CVE-2026-45321 (CVSS 9.6), subraya cómo una cadena de tres vulnerabilidades permitió la publicación de código malicioso con atestación de proveniencia legítima. Este informe desglosa las seis brechas clave explotadas por el gusano y las medidas esenciales para proteger su entorno.
1. Anclar la Publicación de Confianza OIDC a Flujos de Trabajo y Ramas Específicos
El gusano Shai-Hulud explotó una configuración errónea crítica en cómo se implementa a menudo la publicación de confianza OpenID Connect (OIDC), eludiendo incluso la autenticación multifactor (2FA) y la proveniencia firmada. La mayoría de las organizaciones otorgan confianza OIDC a nivel de repositorio, lo que significa que cualquier flujo de trabajo que se ejecute dentro de ese repositorio puede solicitar un token de publicación. Además, el permiso id-token: write se configura con frecuencia a nivel de flujo de trabajo, en lugar de estar estrictamente limitado al trabajo de publicación específico.
El atacante logró astutamente la ejecución de código dentro del flujo de trabajo de liberación legítimo mediante el envenenamiento de la caché. Esto permitió al gusano extraer el token OIDC directamente de la memoria del proceso del runner. Si bien el anclaje de ramas/flujos de trabajo es una buena práctica, resultó insuficiente aquí porque el código malicioso ya se estaba ejecutando dentro del flujo de trabajo supuestamente "anclado". La defensa integral requiere no solo anclar la confianza OIDC a un archivo de flujo de trabajo específico en una rama protegida, sino también restringir estrictamente id-token: write solo al trabajo de publicación. Crucialmente, este trabajo debe ejecutarse desde un espacio de trabajo limpio sin caché no confiable restaurado, evitando que los cachés envenenados reintroduzcan vulnerabilidades.
2. Ir Más Allá de la Proveniencia: Implementar Análisis de Comportamiento en Tiempo de Instalación
Tradicionalmente, un distintivo de proveniencia Sigstore válido se ha considerado prueba suficiente de la seguridad de un paquete. Las herramientas como npm audit signatures pasan la inspección, y los distintivos verdes se aceptan en flujos de trabajo de adquisición y cumplimiento como una puerta de seguridad. Sin embargo, el ataque de Shai-Hulud ha destrozado esta suposición, revelando una vulnerabilidad fundamental en este paradigma.
Todas las 84 versiones maliciosas de TanStack llevaban atestaciones de proveniencia SLSA Build Level 3 válidas y legítimas. Esto marca la primera vez que un gusano npm ampliamente reportado utiliza paquetes con proveniencia válidamente atestada. La proveniencia solo certifica dónde se construyó un paquete, no si la construcción fue autorizada o si el contenido es seguro. Las herramientas de análisis de comportamiento, como el escáner de IA de Socket, detectaron los 84 artefactos maliciosos en seis minutos de su publicación, mientras que la proveniencia no detectó nada. Este incidente subraya que la proveniencia es necesaria pero no suficiente; se debe complementar con análisis de comportamiento dinámico en tiempo de instalación para identificar amenazas que las verificaciones estáticas no pueden.
3. Aislar la Caché de GitHub Actions y Evitar la Ejecución de Código de Forks
Una brecha crítica explotada por Shai-Hulud reside en la forma en que GitHub Actions maneja los cachés y las solicitudes de extracción. Los flujos de trabajo activados por forks y los flujos de trabajo de liberación a menudo comparten el mismo espacio de nombres de caché, y cerrar o revertir una PR maliciosa se trata erróneamente como la restauración de un estado limpio. La acción pull_request_target se utiliza ampliamente para el benchmarking y el análisis del tamaño del paquete con el checkout de PR de forks, lo que crea una superficie de ataque peligrosa.
El atacante envenenó el almacén pnpm a través de un flujo de trabajo pull_request_target activado por fork que extraía y ejecutaba código del fork en el runner base. Esta caché envenenada sobrevivió al cierre de la PR. Cuando un mantenedor legítimo fusionó a main, el flujo de trabajo de liberación posterior restauró la caché envenenada, inyectando binarios maliciosos. Es fundamental aislar la caché de GitHub Actions por límite de confianza e invalidar los cachés después de PRs sospechosas. Además, es una práctica de seguridad deficiente extraer y ejecutar código de forks directamente en flujos de trabajo pull_request_target, ya que esto otorga acceso no confiable a los recursos del runner. Las reglas de protección de rama, como señaló Peyton Kennedy, tampoco se aplican a commits sin historial o asociación de rama, una técnica que el atacante explotó.
4. Auditar optionalDependencies y Referencias de Commits de GitHub
El panorama de las dependencias de paquetes es complejo, y los atacantes a menudo explotan áreas menos escrutadas. Las herramientas de análisis estático y la aplicación de lockfiles generalmente se centran en dependencies y devDependencies, descuidando optionalDependencies. La vulnerabilidad de Shai-Hulud destacó que optionalDependencies con referencias de commits github: que apuntan a commits huérfanos no son marcadas por la mayoría de las herramientas de seguridad, creando un punto ciego peligroso.
El gusano inyectó optionalDependencies que apuntaban a un commit huérfano github: en el fork del atacante. Cuando npm resuelve una dependencia github:, clona el commit referenciado y ejecuta automáticamente los hooks del ciclo de vida, incluido prepare. Esto permitió que el payload malicioso se ejecutara antes de que se completara el paso de instalación del paquete principal. SafeDep confirmó que Mistral nunca lanzó la versión 2.4.6 de PyPI, ya que no hubo commits ni etiquetas. Es imperativo auditar las dependencias opcionales en los lockfiles y los gráficos de dependencias, y bloquear las referencias github: que apuntan a commits que no son de liberación, o a commits sin historial de rama clara.
5. Auditar las Importaciones de Dependencias de Python por Separado y Cubrir Pipelines de IA/ML
Si bien muchas organizaciones han implementado mitigaciones para npm, como la aplicación de lockfiles y la opción --ignore-scripts, estas defensas a menudo se centran únicamente en la pila de JavaScript. Las dependencias de Python, especialmente en los crecientes pipelines de IA/ML, a menudo se asumen seguras si pip install se completa sin errores, y los pipelines de CI/CD para IA/ML son tratados como infraestructura de prueba interna, no como objetivos de ataque a la cadena de suministro.
Microsoft Threat Intelligence confirmó que el paquete PyPI mistralai v2.4.6 ejecuta código malicioso en el momento de la importación, no en la instalación. El código inyectado en __init__.py descarga un payload disfrazado de Hugging Face Transformers. La mitigación --ignore-scripts es irrelevante para la ejecución en tiempo de importación de Python. Paquetes como guardrails-ai@0.10.1 también ejecutan código en la importación. Cualquier repositorio agente con id-token: write en GitHub Actions está expuesto a la misma técnica de extracción de OIDC, poniendo en riesgo claves de API de LLM, credenciales de bases de datos vectoriales y tokens de servicios externos. Es vital auditar las dependencias de Python por separado, considerando que los pipelines de IA/ML son objetivos de alto valor y deben tratarse con la misma rigurosidad de seguridad que otros sistemas de producción.
6. Aislar Máquinas Afectadas Antes de Revocar Tokens Robados
La respuesta estándar a incidentes de seguridad es revocar inmediatamente los tokens comprometidos y luego investigar. La lista de tokens de npm y la revocación instantánea son los primeros pasos instintivos. Sin embargo, el gusano Shai-Hulud ha introducido una táctica de represalia que convierte esta práctica en una trampa peligrosa, transformando una respuesta de seguridad en un evento destructivo.
El gusano instala un daemon persistente (LaunchAgent en macOS / systemd en Linux) que consulta GitHub cada 60 segundos. Al detectar la revocación del token (un error 40X), activa rm -rf ~/, borrando el directorio de inicio del usuario. La descripción del token npm malicioso incluso dice: "IfYouRevokeThisTokenItWillWipeTheComputerOfTheOwner" (SiRevocasEsteTokenBorraráLaComputadoraDelPropietario), y no es un engaño. Microsoft incluso informó un comportamiento destructivo geocercado, con un 1 entre 6 posibilidades de rm -rf / en sistemas de Israel o Irán. Es crítico que, ante una sospecha de compromiso, se aísle e image la máquina afectada antes de revocar cualquier token. Solo una vez que se ha preservado forensemente el host, se deben rotar las credenciales, comenzando por los tokens de npm, seguidos por los PAT de GitHub y las claves de la nube. Además, el gusano instala persistencia en directorios .claude/ y .vscode/, persistiendo más allá de la eliminación del paquete.
La Evolución del Gusano Exige Defensas Evolucionadas
La campaña Shai-Hulud es la quinta ola en ocho meses y está iterando rápidamente. Lo que comenzó con cuatro paquetes SAP se expandió a 84 paquetes TanStack en dos semanas, y luego a 172 paquetes en múltiples ecosistemas. La revelación de que el código del gusano Shai-Hulud completamente armado ha sido "open-sourceado" significa que la amenaza ya no se limita a TeamPCP; cualquier actor de amenazas puede ahora desplegar esta compleja cadena de ataque. Esto incluye el envenenamiento de caché, la extracción de OIDC y la publicación atestada por proveniencia contra cualquier paquete npm o PyPI con un pipeline de CI/CD mal configurado.
"Hemos estado rastreando esta familia de campañas desde septiembre de 2025", dijo Peyton Kennedy, investigadora de seguridad en Endor Labs. "Cada ola ha elegido un objetivo de mayor descarga y ha introducido un vector de acceso técnicamente más interesante. La técnica del commit huérfano aquí es genuinamente novedosa. Las reglas de protección de rama no se aplican a commits que no están en ninguna rama. El espacio de seguridad de la cadena de suministro ha gastado mucha energía en la proveniencia y la publicación de confianza en los últimos dos años. Este ataque atravesó directamente ambos controles porque la brecha no estaba en la firma. Estaba en el alcance."
Esta declaración encapsula la lección crítica de este incidente: la proveniencia nos dice dónde se construyó un paquete, pero no si la construcción fue autorizada. El futuro de la seguridad de la cadena de suministro exige un enfoque multifacético que combine la verificación de proveniencia con un análisis de comportamiento riguroso, una gestión granular de permisos, el aislamiento de cachés y una respuesta a incidentes que tenga en cuenta tácticas de represalia. Los defensores deben iterar y evolucionar tan rápidamente como lo hacen las amenazas.


