Mini Shai-Hulud: La Nueva Oleada de Ataques Supply Chain en npm
La primera quincena de octubre de 2026 ha sido una de las peores rachas de seguridad en la cadena de suministro de npm que se recuerdan. No un único incidente aislado, sino un patrón: paquetes comprometidos que roban credenciales y se autopropagan. En Binary Core hemos revisado nuestros pipelines y este es el análisis y las medidas que aplicamos.
Los incidentes principales
tensorlake@0.5.144 — el dead-man's switch
El 8 de octubre, una cuenta de mantenedor comprometida publicó tensorlake@0.5.144 — un SDK de TypeScript para sandboxes de agentes de IA, con unas 12.000 descargas semanales. El paquete se publicó a través del propio workflow de release del proyecto, por lo que llevaba provenance de npm válido. Parecía una release legítima.
El payload, ejecutado vía hook preinstall, robaba credenciales de GitHub, npm, AWS, GCP, Kubernetes, Vault, claves SSH/GPG, ficheros .env, contraseñas del navegador y configuraciones de herramientas de IA y MCP. Y se replicaba: usaba los tokens robados para republicarse en otros paquetes a los que la víctima tuviera acceso de escritura.
El detalle más perverso: instala un servicio persistente llamado gh-token-monitor que borra el directorio home del usuario si el token de GitHub robado es revocado. Hay que eliminar el monitor antes de rotar cualquier token — el orden de la respuesta importa.
@subql/common — Trusted Publisher abusado
El 5 de octubre, @subql/common@5.8.3 fue publicado con código malicioso tras manipular el workflow de CI/CD del repositorio. La publicación se hizo vía GitHub Actions OIDC (Trusted Publisher), lo que la hace indistinguible de una release legítima. Infostealer más backdoor con reverse shell, ejecutado por postinstall.
Cluster de dependency confusion
Entre el 9 y el 11 de octubre aparecieron paquetes como @galicia-toolkit-nestjs/paas, cloudflare_module, kmf-bootstrap y otros, diseñados para colisionar con nombres de dependencias internas de empresas. Usaban versiones infladas (999.0.3, 100.100.100) para ganar la resolución de dependencias contra registros privados, y native add-ons para exfiltrar tokens de CI y metadatos del host.
El patrón común
Todos estos ataques comparten estructura:
- Ejecución en install time (
preinstall/postinstall) — el código corre antes de que uses el paquete. - Objetivo: credenciales del entorno, no el código del usuario final.
- Autopropagación o persistencia: no es un robo puntual, es un punto de apoyo.
- Abuso de mecanismos de confianza (provenance, OIDC, resolución semver) para parecer legítimos.
Medidas defensivas concretas
En desarrollo local
bash# Configuración global recomendada npm config set ignore-scripts true
ignore-scripts rompe algunos paquetes legítimos (esbuild, sharp), pero puedes habilitar scripts solo donde haga falta o usar npm rebuild selectivamente. El trade-off se ha invertido: ya no es paranoia, es higiene básica.
En CI/CD
- Pin de versiones exactas en
package-lock.jsony revisión de diffs en lockfiles: cualquier paquete nuevo o versión inflada debe saltar a la vista. - Cooling period: retrasa la actualización a versiones publicadas en las últimas 24-72h salvo que sea un parche de seguridad conocido. La mayoría de estas campañas se detectan en horas.
- Secrets de mínimo alcance en CI: el GITHUB_TOKEN por defecto con permisos de solo lectura salvo necesidad explícita.
- Registros privados con scope: configura
@tu-org/*para que resuelva siempre contra tu registry interno — eso neutraliza la dependency confusion.
Comprobación rápida
bashnpm list tensorlake # ¿tienes la 0.5.144? npm view @subql/common@5.8.2 scripts # versiones seguras no tienen postinstall
Conclusión
La cadena de suministro de npm es un blanco porque funciona: un solo npm install ejecuta código arbitrario en máquinas llenas de credenciales valiosas. Las medidas son conocidas desde hace años; la diferencia en 2026 es que ya no son opcionales. ignore-scripts, lockfiles revisados y secrets mínimos deberían ser el default de cualquier equipo.
Binary Core
Equipo Binary Core