El Mayor Ataque a la Cadena de Suministro de npm: Cómo 18 Paquetes con 2.6 Mil Millones de Descargas Fueron Comprometidos — y Por Qué los Hackers Ganaron Casi Nada

En lo que ya se considera el mayor compromiso de la cadena de suministro de npm en la historia, atacantes secuestraron 18 paquetes ampliamente utilizados — incluyendo chalk, debug, ansi-styles y strip-ansi — con un total combinado de 2.6 mil millones de descargas semanales.

El ataque comenzó cuando el mantenedor Josh Junon (qix) fue víctima de phishing y entregó sus credenciales de npm. Con este acceso, los atacantes publicaron actualizaciones maliciosas que contenían un módulo diseñado para robar criptomonedas, interceptando transacciones en navegadores y reemplazando direcciones de billeteras.

La propagación fue increíblemente rápida: en solo dos horas, las versiones maliciosas habían llegado al 10% de todos los entornos en la nube.

Y aun así, pese a la magnitud, los atacantes se llevaron menos de $1,000 en ganancias.

Anatomía del Ataque

Acceso Inicial — Phishing a un Mantenedor

  • Objetivo: Josh Junon (qix), mantenedor de proyectos npm críticos.
  • Vector: Correo de phishing desde un dominio falso (npmjs[.]help).
  • Señuelo: Amenaza de bloqueo de cuenta si no actualizaba su 2FA.
  • Endpoint de exfiltración de credenciales: https://websocket-api2[.]publicvm.com/images/jpg-to-png.php
  • Con esto, los atacantes obtuvieron control total de la cuenta de Junon en npm.

Inyección de Payload Malicioso

Los atacantes publicaron versiones comprometidas de 18 paquetes clave, incluyendo:

  • chalk (300M descargas semanales)
  • debug (357M)
  • ansi-styles (371M)
  • supports-color (287M)
  • strip-ansi (261M)
  • wrap-ansi (198M)
  • y otros (color-convert, slice-ansi, simple-swizzle, etc.)

Estos paquetes están profundamente integrados en el ecosistema Node.js, lo que significa que casi cualquier proyecto depende indirectamente de ellos.

Lógica del Malware

  • Contexto de Ejecución: Solo en entornos de navegador, no en servidores Node.js.
  • Hooks Inyectados:
    • window.fetch
    • XMLHttpRequest
    • APIs Web3 (window.ethereum, Solana, etc.)
  • Comportamiento:
    • Interceptaba solicitudes de transacciones.
    • Reemplazaba direcciones de billetera con las del atacante.
    • Exfiltraba datos de transacciones.

En resumen, un skimmer de criptomonedas en el navegador.

Velocidad de Propagación

  • Según Wiz:
    • 99% de entornos en la nube usan al menos uno de los paquetes afectados.
    • En 2 horas, el 10% de los entornos ya tenían versiones maliciosas.
  • Demostración clara de que los ataques a la cadena de suministro se propagan más rápido que cualquier malware tradicional.

Evaluación del Impacto

  • Propagación técnica: Enorme — miles de millones de descargas + 10% de impacto en la nube.
  • Impacto de seguridad: Limitado — payload demasiado enfocado (solo Web3 en navegadores).
  • Ganancias de los atacantes:
    • ~$429 en ETH
    • ~$46 en SOL
    • ~$20 en memecoins
    • ~$100–200 entre BTC/Tron/BCH/LTC
    • Total ≈ $600–$1,000

Ironía: Los atacantes comprometieron los paquetes más grandes de npm pero escribieron un payload inútil para la mayoría de los entornos (servidores y pipelines de CI/CD).

Escenarios de Explotación (Estilo Red Team)

Escenario 1 — Payload en Servidores

En lugar de un skimmer de Web3, podrían haber:

  • Exfiltrado credenciales de AWS/GCP en CI/CD.
  • Movido lateralmente en infra en la nube.
  • Insertado persistencia en pipelines.

Impacto: Brecha multi-nube masiva.

Escenario 2 — Infección en Cadena

El malware podría haber creado paquetes secundarios comprometidos dentro de node_modules, que a su vez publicaran versiones maliciosas.

  • Esto habría cascado el ataque por árboles completos de dependencias.

Escenario 3 — Espionaje Silencioso

Payload diseñado para:

  • Extraer claves API de .env.
  • Robar tokens de SDKs cloud.
  • Minar secretos de entornos de build.

Impacto: Ciberespionaje a largo plazo, en lugar de robo trivial de cripto.

Lecciones Aprendidas

  1. Los mantenedores open source son objetivos críticos. Un solo phish = compromiso global.
  2. La propagación es inmediata. Horas, no días.
  3. El payload importa. El fracaso fue del malware, no del acceso.
  4. La próxima vez no habrá error.

Recomendaciones

Para Desarrolladores

  • Usar 2FA resistente a phishing (llaves FIDO2).
  • Fijar versiones con package-lock.json.
  • Auditar actualizaciones (diffs y llamadas sospechosas).
  • Esperar 24–48h antes de actualizar paquetes críticos.
  • Monitoreo en runtime: detectar conexiones inesperadas.

Para Ecosistema / Vendors

  • Detección de anomalías en el registro: Cambios repentinos en paquetes críticos.
  • Rollback automático de versiones sospechosas.
  • Verificación adicional para mantenedores de alto impacto.
  • Firmas de dependencias para verificar integridad.
  • Alertas comunitarias rápidas al detectar compromisos.

Este fue el mayor compromiso en la historia de npm — miles de millones de descargas, 10% de la nube afectada en 2 horas.

El único motivo por el cual no fue catastrófico: los atacantes eligieron mal su payload. Se enfocaron en robar criptomonedas en navegadores, ignorando que estos paquetes corren mayormente en servidores, CI/CD y entornos en la nube.

Un alivio, sí. Pero también una advertencia:

  • El acceso fue perfecto.
  • El malware fue lo que falló.
  • La próxima vez, los atacantes sabrán hacerlo mejor.

La cadena de suministro open source sigue siendo el eslabón más débil.