La mayoría de los ataques a la cadena de suministro necesita que una persona cometa un error. Este necesitó que una persona cometiera un error una vez, y después siguió solo.
Qué pasó
El 4 de agosto de 2026, unos atacantes obtuvieron las credenciales del mantenedor de keyv y cacheable, paquetes npm pequeños y poco vistosos que sostienen buena parte del JavaScript que existe. Solo la familia keyv acumula bastante más de mil millones de descargas mensuales.
Lo que publicaron no fue simplemente una versión con puerta trasera. Fue un gusano.
El paquete malicioso traía un hook preinstall, una función legítima de npm que ejecuta comandos antes de instalar el paquete. Ese hook soltaba un runtime de Bun y ejecutaba una carga ofuscada que rastreaba la máquina en busca de credenciales: tokens de npm y GitHub, llaves de AWS, GCP, Azure y Alibaba Cloud, cuentas de servicio de Kubernetes, llaves SSH, tokens de Vault y claves de API de servicios de IA. Los investigadores contaron más de 300 patrones de credencial en el cosechador. El botín se comprimía, se cifraba y salía.
Después venía lo que lo convirtió en gusano. Donde encontraba un token de npm con permisos de publicación que no exigiera autenticación de dos factores, enumeraba todos los paquetes a los que esa cuenta podía escribir e infectaba cada uno. Otros desarrolladores instalaban esos paquetes, en otras máquinas, con otros tokens.
En unas cuatro horas, la campaña había publicado más de 2,200 versiones maliciosas en más de 400 paquetes distintos. Entre las organizaciones alcanzadas aparecen Deliveroo, Picsart, Qlik y ServiceTitan. El malware desciende de la familia Shai-Hulud; más allá de eso, la atribución sigue sin confirmarse, y ahí la dejamos.
Tres cosas que explota, y ninguna es un error de programación
npm install ejecuta código. Los hooks de instalación existen por razones legítimas: compilar módulos nativos, preparar un paquete después de descargarlo. Pero la consecuencia es que agregar una dependencia ejecuta código arbitrario en la máquina que instala, antes de que nadie haya revisado una sola línea. Cada npm install es un acto de confianza, y casi todos se hacen sin pensarlo así.
Tu servidor de compilación es el objetivo más rico que tienes. Los desarrolladores piensan en sus laptops. Los atacantes piensan en CI. Un agente de compilación guarda credenciales de despliegue, llaves de nube, tokens de registro y material de firma, todo en variables de entorno y todo accesible para cualquier proceso que la compilación lance. Una laptop da el acceso de una persona; un servidor de compilación da el de la organización.
Los tokens de publicación sin MFA convierten un compromiso en muchos. La propagación del gusano dependía por completo de encontrar tokens capaces de publicar sin un segundo factor. Donde los mantenedores tenían 2FA obligatorio para publicar, la cadena se cortaba.
Esto no es solo un problema de desarrollo
Es tentador archivarlo como "algo del equipo de ingeniería". Es un error, por dos razones.
Primero, casi toda organización hoy produce software de algún tipo, aunque sea un sitio web, una herramienta interna o unos scripts de automatización. Si algo en tu negocio ejecuta npm install, pip install o composer install dentro de un pipeline automatizado, tienes esta exposición.
Segundo, las credenciales que este gusano buscaba no son credenciales de desarrollo. Son llaves de nube de producción, acceso a Kubernetes y tokens de gestores de secretos. Un compromiso que empieza en un pipeline de compilación termina en la infraestructura que opera el negocio. El radio de impacto lo define hasta dónde llega el servidor de compilación, no en qué estaba trabajando la persona que desarrolla.
Qué hacer en concreto
Fija tus dependencias y versiona el lockfile. Un lockfile hace que una compilación instale exactamente las versiones que probaste, y no lo más nuevo que hubiera a las 09:00 UTC el día de un ataque. Las organizaciones que peor la pasan en campañas rápidas son las que resuelven versiones de cero en cada compilación.
Desactiva los scripts de instalación donde puedas. npm ci --ignore-scripts evita el hook preinstall que transportó esta carga. Algunos paquetes sí necesitan sus scripts; permítelos en una lista explícita en vez de habilitarlos todos por defecto.
Trata el servidor de compilación como producción. Credenciales de vida corta en lugar de llaves permanentes, acotadas exactamente a lo que el pipeline necesita. Nada de llaves de administrador de nube compartidas en las variables de CI. Ejecutores separados para trabajo confiable y no confiable.
Exige MFA para publicar lo que distribuyes. Si tu organización mantiene paquetes públicos o internos, este es el control que rompe la cadena de propagación.
Conoce de qué dependes. Un inventario de componentes de software suena burocrático hasta que un aviso nombra 400 paquetes y necesitas saber en una hora si alguno es tuyo. La pregunta "¿nos afecta?" debería tomar minutos, no días.
Rota ante la sospecha, no ante la confirmación. Si un paquete comprometido llegó a una máquina con credenciales, asume que esas credenciales salieron. Rotar es barato; una investigación que intente probar una negativa no lo es.
El resumen
ChainDrop no rompió npm. Usó npm tal como está diseñado —hooks de instalación, tokens de publicación, dependencias transitivas— y ese diseño asume que las cuentas de los mantenedores no están comprometidas. Una lo estuvo, y el resto fue aritmética.
La postura defensiva no es dejar de usar código abierto, lo que no es posible ni sensato. Es aceptar que tu árbol de dependencias es superficie de ataque que no escribiste, mantener cortas y acotadas las credenciales que viven cerca de él, y poder responder rápido cuando aparezca el aviso.
Fuentes
- Shai-Hulud strikes again: CHAINDROP worm hits 400+ npm packages — Elastic Security Labs
- 'ChainDrop' worm compromises hundreds of popular npm packages — Datadog Security Labs
- ChainDrop npm worm: Bun-loaded CI/CD credential harvester — StepSecurity
- ChainDrop: the Mini Shai Hulud npm worm's latest wave hits keyv and cacheable — Expel



