Mini Shai-Hulud: un gusano de cadena de suministro que explotó TanStack y el ecosistema npm.
El día de ayer (10/05/2026) la comunidad de npm y PyPI vivió un nuevo capítulo de Mini Shai-Hulud, un campaña de ataque de cadena de suministro dirigida por el grupo TeamPCP que comprometió paquetes de TanStack, Mistral AI, UiPath, OpenSearch, guardrails‑ai y más. El impacto se estimó en más de 170 paquetes y 500M+ de descargas acumuladas, con un nivel de severidad crítico (CVSS ≈ 9.6) y un CVE asociado: CVE‑2026‑45321. 1 ¿Qué pasó? El ataque inyectó código malicioso en paquetes de npm muy populares, empezando por el ecosistema de TanStack (por ejemplo, @tanstack/react‑router, @tanstack/vue‑router, etc.), y luego se extendió a Mistral AI, UiPath, OpenSearch, guardrails‑ai y otros. El malware, un gusano de credenciales (credential‑stealing worm), hacía lo siguiente al ejecutarse durante npm install o cuando se usaba el paquete en CI/CD. • Robaba tokens de GitHub, npm, AWS, GCP, Azure, Kubernetes, Vault, IDEs y hasta carteras de cripto. • Se auto‑replegaba hacia otros paquetes que el mantenedor pudiera publicar, propagándose en el ecosistema. • Establecía persistencia en máquinas de desarrolladores (Claude Code, VS Code, servicios de sistema) y podía borrar datos si se revocaba cierto token. También se ha visto una variante en PyPI (guardrails‑[email protected], [email protected]) que descarga y ejecuta un payload remoto sin verificación de integridad, ampliando el ataque a Python y otros ecosistemas. 2 ¿Cómo sucedió? El ataque combinó ingeniería de engaños en GitHub con un mal uso de GitHub Actions y OIDC, sin necesidad de robar directamente el token de npm. El flujo básico fue: 1. Inyección en el fork: ◦ Atacante hace fork de TanStack/router y sube un commit con un paquete @tanstack/setup que contiene un script prepare malicioso que ejecuta bun run tanstack_runner.js. ◦ El commit es “huérfano” y se hace pasar por algo legítimo gracias a la URL de GitHub. 2. Envenenamiento de caché en GitHub Actions: ◦ El workflow de CI/CD de TanStack ejecuta código del fork, lo que contamina el caché de pnpm y causa que se instale código controlado por el atacante. 3. Extracción de token OIDC y publicación de paquetes: ◦ El payload accede a la memoria del proceso del runner (/proc/*/mem) y extrae el OIDC token legítimo de GitHub, que el sistema de SLSA considera confiable. ◦ El atacante usa ese token para publicar versiones falsas de los paquetes de TanStack directamente al registro de npm, con probidad de SLSA válida, lo que hace que el paquete “se vea limpio” incluso con firmas. 4. Auto‑propagación del worm: ◦ El malware busca tokens de npm con bypass_2fa, enumera todos los paquetes del mantenedor y vuelve a publicar versiones comprometidas, generando el efecto de “gusano” en el ecosistema. 3 ¿Qué debes tener en cuenta? Este incidente recalca varios peligros que ya no son "teóricos": • GitHub Actions + OIDC = nuevo vector de ataque Un token OIDC, aunque sea de corta vida, puede usarse para publicar paquetes y firmarlos con SLSA, dando pinta de legítimo a un paquete malicioso. 4 ¿Qué hacer ahora? Si usas npm/PyPI en producción, estos pasos no son opcionales: • Identificar exposición: ◦ Revisa package‑lock.json / yarn.lock / pnpm‑lock.yaml (y requirements.txt o pipenv.lock en Python) buscando versiones afectadas de @tanstack/*, @uipath/*, mistralai, guardrails‑ai, @opensearch‑project/opensearch, etc. ◦ Busca router_init.js o setup.mjs en el árbol de node_modules y en tus tarballs. • Rotar todos los secretos potencialmente expuestos: ◦ Tokens de npm, GitHub, AWS, Vault, Kubernetes, CI/CD, etc. ◦ Wiz y StepSecurity recomiendan rotar cualquier token si el entorno instaló alguna versión afectada, por el alcance de lo que el malware puede extraer. • Eliminar persistencia en máquinas de desarrolladores: ◦ Borrar archivos como .claude/router_runtime.js, .claude/setup.mjs, .vscode/setup.mjs y revisar settings.json y tasks.json. ◦ En macOS/Linux, eliminar el servicio gh‑token‑monitor antes de tocar tokens de GitHub para evitar que el wiper se dispare. • Bloquear infraestructura de C2: ◦ Bloquear a nivel DNS/proxy dominios como git‑tanstack.com, *.getsession.org y otras IPs/C2 documentadas por StepSecurity, Wiz, Socket, etc. 5 ¿Cómo protegerse a futuro? Este ataque es una hoja de ruta de hardening para cualquier equipo que consuma paquetes de terceros: • Reducir el alcance de OIDC en GitHub Actions: ◦ Usar solo id‑token: write en el job que realmente publica, y evitar OIDC en workflows de test/CI generales. • Hardening de GitHub Actions: ◦ Asegurar que pull_request_target solo se ejecute en ramas protegidas y que no se ejecute código de forkeos sin validación. ◦ Limpiar caché de CI y usar restricciones de permisos entre fork y base. • Adoptar buffers de tiempo para nuevos paquetes: ◦ Estrategias como “cooldown” de versiones nuevas (nuevas versiones de npm bloqueadas por 24–72 horas) dan margen para detectar y bloquear estos ataques antes de que lleguen a producción. • Monitoreo de tiempo de ejecución en CI: ◦ Herramientas que monitorean tráfico de red, lectura de memoria de runner (/proc/*/mem) o uso de sudo / python3 de forma inusual ayudan a detectar estas inyecciones que evitan el escaneo estático. • No confiar ciegamente en “provenance” o SLSA: ◦ Que un paquete tenga badges de SLSA no garantiza que el pipeline no haya sido comprometido; debes ver el provenance como una parte de tu cadena de confianza, no como la única. 6 Reflexión para líderes técnicos y de seguridad: Este episodio muestra que: • La cadena de suministro ya es un vector de ataque operativo y automatizado. • Un gusano puede escalar de un solo paquete a docenas de repositorios y nubes en cuestión de horas. • Debes combinar: ◦ Control de cambios de dependencias. ◦ Hardening de CI/CD. ◦ Monitoreo de tiempo de ejecución. ◦ Respuesta rápida de rotación de credenciales. Enlace de referencia rápida: • Vulnerabilidad CVE‑2026‑45321 (TanStack): detalle de impacto y severidad. • Mini‑Shai‑Hulud en npm y PyPI: artículos de The Hacker News, Socket, StepSecurity y Wiz con IOCs y pasos de remediation.
