Ataque supply chain masivo: TanStack, Mistral AI y 170 paquetes npm comprometidos
El 11 de mayo de 2026 un ataque coordinado comprometió 170 paquetes npm y 2 de PyPI en 5 horas, incluyendo todo el ecosistema TanStack Router, los SDKs de Mistral AI y OpenSearch. Análisis técnico del ataque y qué hacer si estás afectado.
El 11 de mayo de 2026, en un window de cinco horas, un atacante publicó versiones maliciosas de 170 paquetes npm y 2 de PyPI en el mayor ataque coordinado de supply chain del año. El objetivo era claro: robar credenciales de AWS, GitHub, Vault y npm de desarrolladores y pipelines de CI/CD.
Si usas TanStack Router, los SDKs de Mistral AI o tienes un pipeline que instaló estas dependencias en esa fecha, necesitas leer esto.
Qué paquetes están afectados
Los objetivos de alto perfil organizados por ecosistema:
| Paquete | Versiones maliciosas | Descargas semanales |
|---|---|---|
@tanstack/react-router | 1.169.5, 1.169.8 | 3M+ |
@tanstack/vue-router | 1.169.5, 1.169.8 | — |
@mistralai/mistralai | 2.2.2, 2.2.3, 2.2.4 | — |
@opensearch-project/opensearch | 3.5.3, 3.6.2, 3.7.0, 3.8.0 | 1.3M |
mistralai (PyPI) | 2.4.6 | — |
guardrails-ai (PyPI) | 0.10.1 | — |
En total: 42 paquetes del ecosistema @tanstack, 3 de @mistralai, 65 de @uipath, y varios más.
Cómo funciona el ataque
El atacante utilizó dos mecanismos de entrega distintos según el paquete objetivo:
Variante Mistral AI: hook preinstall
Los paquetes Mistral reemplazaron todos los scripts de build con un único hook preinstall que descarga el runtime Bun desde GitHub y ejecuta el payload:
// package.json de @mistralai/mistralai@2.2.2 (comprometido)
{
"scripts": {
"preinstall": "node setup.mjs"
}
}
// setup.mjs (simplificado)
const BUN_VERSION = '1.3.13';
// Descarga Bun desde github.com/oven-sh/bun/releases
// Ejecuta router_init.js (payload de 2.2MB ofuscado)
Variante TanStack: optionalDependencies a commit malicioso
Más sutil. El package.json de los paquetes TanStack no modificó el bloque scripts. En su lugar, inyectó una optionalDependency que apuntaba a un commit malicioso en el repositorio oficial tanstack/router:
// package.json de @tanstack/react-router@1.169.5
{
"optionalDependencies": {
"@tanstack/setup": "github:tanstack/router#79ac49ee..."
}
}
Ese commit contenía el payload y un prepare script que lo ejecutaba via Bun. El atacante tenía acceso de escritura al repositorio GitHub de TanStack, lo que significa credenciales comprometidas más allá de npm.
Qué hace el payload
El payload (router_init.js, 2.2MB, un único fichero ofuscado) implementa un framework modular de robo de credenciales:
- AWS:
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, metadata de instancia via169.254.169.254 - GitHub: tokens
ghp_*,gho_*,ghs_*, OIDC tokens de Actions - npm: tokens
npm_* - HashiCorp Vault:
VAULT_TOKENenlocalhost:8200
Las credenciales robadas se exfiltran via el protocolo Session (mensajería onion-routed sobre la red Oxen), no via un dominio C2 convencional. Esto hace que el bloqueo por dominio sea inefectivo.
El vector de propagación más preocupante
Lo más alarmante del ataque es el mecanismo de auto-propagación. El payload usa las credenciales GitHub robadas para commitear ficheros maliciosos en los repositorios de la víctima:
.claude/settings.json ← envenena Claude Code
.claude/setup.mjs ← se ejecuta al abrir el proyecto
.vscode/tasks.json ← envenena VS Code
.vscode/setup.mjs ← se ejecuta al abrir el proyecto
.claude/router_runtime.js ← copia completa del payload (2.2MB)
Cualquier developer que haga git pull de una rama comprometida y abra el proyecto en VS Code o con Claude Code ejecuta el payload sin ninguna acción explícita.
Qué hacer ahora
1. Verificar tu lockfile:
# Buscar versiones comprometidas de TanStack
npm ls | grep -E "@tanstack/react-router|@tanstack/vue-router"
# Verificar OpenSearch
npm ls | grep "@opensearch-project/opensearch"
2. Si usas Python, verificar el entorno:
pip show mistralai guardrails-ai
# Si aparece mistralai 2.4.6 o guardrails-ai 0.10.1, el entorno está comprometido
# Verificar si existe el payload en disco:
ls -la /tmp/transformers.pyz
3. Si algún runner de CI/CD instaló paquetes comprometidos:
Rota inmediatamente todos los tokens presentes en ese entorno: GitHub tokens, npm tokens, AWS credentials, Vault tokens. Trátalos como comprometidos, no como potencialmente comprometidos.
4. Auditar ramas del repositorio:
# Buscar los ficheros de configuración maliciosos
git log --all --full-history -- ".claude/settings.json" ".vscode/tasks.json"
La lección más importante
Este ataque ilustra por qué la seguridad de supply chain no puede depender de “confiar en paquetes conocidos”. El atacante comprometió repositorios GitHub de proyectos legítimos para entregar el payload desde infraestructura oficial. Los mecanismos de verificación habituales (firma de commits, revisión de PRs) no habrían detectado el vector via optionalDependencies.
Las medidas estructurales que sí ayudan:
- Lockfiles con integridad verificada (
pnpm/yarnconintegrityhash). - Dependency pinning con revisión de cambios de versión en PRs.
- Restricción de scripts de
preinstall/postinstallen entornos de CI:npm install --ignore-scripts. - Sandboxing de instalaciones en pipelines de CI para limitar el blast radius.
Los ataques de supply chain de 2026 se están volviendo más sofisticados, más coordinados y más difíciles de detectar con las herramientas tradicionales.