22 minutos. Entre las 01:44 y las 02:06 UTC del 19 de mayo de 2026, alguien publicó 631 versiones maliciosas en 314 paquetes npm. El vector fue el account takeover de la cuenta npm atool, que mantenía 547 paquetes. Los paquetes tenían 16 millones de descargas semanales agregadas, y echarts-for-react solo tenía 3,8 millones por mes. Analizamos el ataque y la señal es clara: cuando la supply chain se vuelve vector, el tiempo de respuesta de la defensa necesita ser menor que el tiempo del ataque.
La escala: 22 minutos, 631 versiones, 314 paquetes
Los números asustan por la densidad temporal. En 22 minutos, se publicaron 631 versiones maliciosas en 314 paquetes npm. El atacante publicó dentro de los paquetes legítimos, con versiones incrementadas automáticamente, no creó paquetes nuevos, infectó los existentes.
La cuenta atool mantenía 547 paquetes. Los paquetes afectados sumaban 16 millones de descargas semanales agregadas. echarts-for-react solo tenía 3,8 millones de descargas por mes. Cada versión publicada inyectaba un hook preinstall que ejecutaba un script Bun ofuscado de 498KB. Bun en lugar de Node fue una elección deliberada para evadir escáneres basados en Node.js.
La recolección: 20 categorías de credenciales en un solo script
El script Bun recolectaba 20 categorías de credenciales: AWS keys, GitHub PATs, npm tokens, GCP, Azure, Kubernetes, SSH keys, Docker auth, cadenas de conexión de base de datos, Stripe keys, Slack tokens. La exfiltración usaba la GitHub API como dead-drop, las credenciales se commiteaban en repositorios atacantes con nombres de Dune, como harkonnen-melange-742.
La elección de Bun no es accidental. Los escáneres tradicionales de supply chain están calibrados para Node.js. Un runtime diferente evade las firmas conocidas, las heurísticas de AST y los patrones de comportamiento. Cuando la defensa asume Node, el atacante usa Bun.
La persistencia: inyección de workflow, hooks de IA y dead-man switch
Después de la recolección venía la persistencia. Inyección de workflow en GitHub Actions: un workflow llamado "Run Copilot" que volcaba todos los secrets vía toJSON(secrets). Hooks en agentes de IA: .claude/settings.json con un hook SessionStart ejecutando node .claude/setup.mjs. Cada vez que un dev abría una sesión de Claude Code, el malware se reejecutaba.
Había además un daemon del sistema llamado kitty-monitor. Y un dead-man switch: si la víctima revocaba el token de GitHub robado, el daemon ejecutaba rm -rf ~/. No es solo exfiltración, es represalia. El atacante transforma la defensa en el gatillo de destrucción.
La atribución: TeamPCP, UNC6780 y el linaje Shai-Hulud
El ataque fue atribuido a TeamPCP, rastreado como UNC6780 por el Google Threat Intelligence Group. Al día siguiente, según GitHub, la brecha fue confirmada: 3.800 repositorios privados exfiltrados, incluyendo github-mcp-server y github-oauth-proxy. TeamPCP ofreció los repositorios robados por 50.000 dólares, no era rescate, era venta. Según OpenAI, dos dispositivos corporativos fueron comprometidos.
Este es el punto más reciente de un linaje que comenzó en septiembre de 2025. Shai-Hulud original: 500 paquetes, gusano autorreplicante. Después 2.0: 796 paquetes. Después SANDWORM_MODE. Después Bitwarden CLI. Después TanStack. Después @antv. En olas anteriores, el mismo grupo falsificó provenance SLSA Build Level 3 válida, y paquetes maliciosos pasaron la verificación criptográfica. El caso fue catalogado como CVE-2026-45321, CVSS 9.6.
La provenance prueba dónde se construyó. Falta probar si es seguro.
El ecosistema: 454.600 paquetes maliciosos en 2025, 1,8 millones a mediados de 2026
Según datos de ecosistema, 454.600 paquetes maliciosos nuevos en 2025. 1,8 millones acumulados a mediados de 2026. 96,6% en npm. La escala no es de ataques puntuales, es de operación industrializada.
Según npm, la versión 12 lanzada en julio de 2026 desactivó los install scripts por defecto y pasó a exigir staged publishing con aprobación humana y 2FA. Esto ayuda contra los hooks preinstall, pero no resuelve el account takeover ni los hooks en agentes de IA. La defensa necesita ir más allá del registry.
Los controles de Tech86 para supply chain con agentes de IA
Cuando Tech86 implementa controles de supply chain para clientes que usan agentes de IA, el principio base es directo. Ningún package.json ni lockfile modificado por un agente de IA entra sin merge gate humano. Sandbox sin credenciales persistidas. Egress allowlist. Hooks de PreToolUse que exigen --ignore-scripts.
No es paranoia. Es lo mínimo frente a un atacante que planta hooks en .claude/settings.json y hace inyección de workflow en GitHub Actions. La superficie de ataque ahora incluye la configuración del propio agente de IA.
Conclusión: el tiempo de respuesta de la defensa necesita ser menor que el tiempo del ataque
22 minutos de publishing. 24 horas después, GitHub confirmó la brecha. El tiempo de respuesta de tu defensa necesita ser menor que el tiempo del ataque.
Lo repetimos: la provenance prueba dónde se construyó, no si es seguro. Los install scripts desactivados por defecto ayudan, pero no resuelven el account takeover. La defensa real es merge gate humano para cambios de agentes de IA, sandbox sin credenciales persistidas, egress allowlist y hooks PreToolUse que exijan --ignore-scripts. En Tech86 ayudamos a empresas a implementar exactamente esos controles, antes de que lleguen los 22 minutos del próximo ataque.