npm bajo ataque: por qué la cadena de suministro de JavaScript se ha convertido en un objetivo crítico
En las últimas semanas y meses, el ecosistema de npm ha vivido algunos de los incidentes de supply chain más serios de su historia reciente. El problema no es npm como herramienta en sí, sino algo más delicado: atacantes que comprometen paquetes legítimos o cuentas de maintainers para introducir malware dentro de dependencias que millones de proyectos instalan automáticamente.
Y ahí está el verdadero peligro. En JavaScript no instalas solo una librería: instalas una cadena entera de confianza. Si esa cadena se rompe en un punto, el impacto puede multiplicarse muy rápido.
Qué está pasando realmente
El patrón se repite con bastante claridad:
- Un atacante roba tokens o credenciales de npm o GitHub a un maintainer.
- Publica una versión maliciosa de un paquete legítimo.
- Equipos y desarrolladores actualizan dependencias con normalidad.
- El malware se ejecuta automáticamente mediante scripts como
postinstallopreinstall.
Ese flujo convierte un gesto cotidiano como este:
npm install
en una posible puerta de entrada para malware, robo de secretos o compromiso del entorno de desarrollo.
Los casos recientes más graves
Entre los incidentes más preocupantes destacan varios compromisos de alto perfil:
- paquetes del ecosistema TanStack, incluyendo piezas como
react-queryyquery-core - el compromiso de Axios
- campañas como Shai-Hulud, un malware autorreplicable pensado para robar tokens y propagarse a otros paquetes y repositorios
Lo importante aquí no es solo el nombre de las librerías, sino su posición dentro del ecosistema. Cuando un paquete muy usado cae, no afecta a un proyecto aislado: afecta potencialmente a miles o millones de instalaciones indirectas.
El caso Axios fue especialmente serio
El incidente de Axios destacó por un motivo evidente: es una dependencia extremadamente popular.
Según el análisis citado de Google Cloud, el compromiso se produjo a través de la cuenta del maintainer. A partir de ahí se publicaron versiones maliciosas que incluían una dependencia oculta llamada plain-crypto-js, utilizada para desplegar un RAT (Remote Access Trojan).
Eso significa que un simple:
npm install axios
podía terminar instalando malware en:
- Windows
- macOS
- Linux
Cuando una librería con más de cien millones de descargas semanales entra en juego, el incidente deja de ser anecdótico y pasa a ser un problema estructural para toda la industria.
Por qué esto es tan peligroso en JavaScript
El ecosistema JavaScript depende de terceros de una forma especialmente intensa.
Muchos proyectos tienen:
- una o dos dependencias directas aparentemente inocentes
- cientos o miles de dependencias transitivas
Instalas React, Next o cualquier herramienta moderna, y detrás entra una red enorme de paquetes que casi nadie revisa manualmente uno por uno.
Ese modelo tiene ventajas de velocidad y reutilización, pero también un coste claro: la superficie de ataque crece muchísimo.
Un estudio reciente sobre propagación de vulnerabilidades en redes de dependencias de npm apunta además a que una parte significativa del ecosistema arrastra problemas de seguridad a través de su cadena de dependencias. En otras palabras: el riesgo no vive solo en tu código, sino en todo lo que tu código decide confiar.
Qué puede hacer el malware una vez entra
Estos ataques ya no buscan solo romper algo o llamar la atención. Buscan acceso persistente y monetizable.
En campañas recientes, el malware ha llegado a:
- robar credenciales
- extraer tokens de npm
- filtrar secretos de CI/CD
- capturar claves cloud
- acceder a cookies
- robar sesiones o accesos de GitHub
- propagarse a otros repositorios
- e incluso borrar directorios completos con comandos destructivos
Eso cambia por completo la percepción del riesgo. Ya no hablamos de una dependencia rota o un bug molesto: hablamos de comprometer la máquina del desarrollador, el pipeline y, desde ahí, toda la cadena de publicación.
Qué está cambiando ahora
Tanto npm como GitHub han endurecido varias medidas para reducir este tipo de incidentes:
- MFA obligatorio
- expiración de tokens
- trusted publishing
- OpenID Connect
- mecanismos de firma y verificación de paquetes
Son pasos importantes, pero no suficientes por sí solos. Los atacantes también están evolucionando y ya no dependen solo del paquete malicioso tradicional.
Ahora también vemos:
- ataques a pipelines de CI/CD
- malware que se disfraza dentro de builds aparentemente legítimos
- campañas de typosquatting
- robo de secretos en GitHub Actions
La defensa está mejorando, sí, pero el terreno también se está volviendo más sofisticado.
Qué deberías hacer hoy como desarrollador
No existe una bala de plata, pero sí hay varias medidas simples que reducen bastante la exposición sin convertir tu flujo en una auditoría forense.
1. Activa MFA en npm y GitHub
Es lo más básico y, a la vez, una de las defensas más rentables.
Muchas cadenas de compromiso empiezan por una cuenta débil, un token expuesto o una credencial reutilizada.
2. No instales ni actualices paquetes a ciegas
La costumbre peligrosa no es solo npm update. También lo es instalar cualquier cosa rápido porque la viste en un hilo, un vídeo o una respuesta de IA.
Antes de meter una dependencia nueva, revisa al menos:
- si el paquete realmente es el oficial
- cuántas descargas y actividad real tiene
- quién lo mantiene
- si su repositorio parece legítimo
- si la versión salió hace unas horas y aún no ha sido revisada por nadie
Un hábito muy simple y bastante sano es este: si no conoces el paquete, no lo instales en caliente en un proyecto importante.
3. Fija versiones concretas
Más que actualizar por inercia, suele ser mejor instalar versiones concretas y moverlas con intención.
npm install axios@1.12.0
Eso te da más control que dejar rangos demasiado amplios y reduce la posibilidad de traer cambios inesperados en la siguiente instalación.
Si el proyecto ya usa archivo de bloqueo, mantenlo siempre versionado en Git.
4. pnpm, yarn o bun pueden ayudarte, pero no arreglan esto por sí solos
Cambiar de gestor de paquetes no elimina el problema de supply chain.
Si un paquete legítimo ha sido comprometido y tú lo instalas con npm, pnpm o yarn, el riesgo principal sigue existiendo. El malware no deja de ser malware por cambiar de CLI.
Sí hay matices útiles:
pnpmsuele imponer una estructura más estricta de dependenciasyarnypnpmpueden darte flujos de bloqueo y resolución cómodos- algunos equipos prefieren sus políticas de workspace o su rendimiento
Pero eso es una mejora operativa, no una solución de seguridad por sí misma.
Y algo importante: usar npx para ejecutar herramientas de una sola vez tampoco es automáticamente más seguro. De hecho, ejecutar paquetes remotos sin instalar apenas contexto puede ser todavía peor si no sabes exactamente qué estás lanzando.
5. Revisa los scripts de instalación
Muchos de estos ataques entran por scripts como postinstall o preinstall.
Si sospechas de un paquete, revisa su package.json antes de normalizarlo en tu proyecto.
En entornos sensibles, especialmente CI, puede tener sentido instalar sin scripts:
npm install --ignore-scripts
No siempre servirá, porque algunos paquetes legítimos sí necesitan ese paso, pero como regla defensiva es bastante más sencilla de entender que muchas recomendaciones más complejas.
6. Usa instalaciones reproducibles cuando el proyecto ya está cerrado
Aquí sí entra npm ci, pero no como mantra.
npm ci
Tiene sentido sobre todo en CI, despliegues y entornos donde quieres instalar exactamente lo que ya estaba fijado en el package-lock.json, sin recalcular nada nuevo.
No es la solución mágica, pero sí una buena forma de evitar sorpresas en proyectos ya estabilizados.
7. Pasa una revisión mínima antes de confiar
No hace falta montar un SOC para mejorar bastante la seguridad. A veces una revisión de un minuto ya filtra mucho:
- mirar el
package.json - mirar si tiene scripts raros
- abrir el repo
- comprobar si el paquete tiene actividad real
- buscar si ya hay alertas públicas
Además, herramientas como npm audit, Socket, Snyk, Dependabot u osv-scanner pueden ayudarte a automatizar parte de esa revisión.
8. Desconfía de paquetes pequeños, nuevos o sospechosos
Hoy son especialmente sensibles los paquetes:
- recién publicados
- con pocas descargas
- con nombres sospechosamente parecidos a otros
- con maintainers poco trazables
- que piden entrar en tu proyecto sin una razón clara
No todo paquete pequeño es peligroso, pero ahora mismo instalar dependencias aleatorias sin revisar contexto es una mala práctica clara.
Lo más importante: esto ya no va solo de npm
El mensaje de fondo es más amplio.
Ya no estamos ante la era de los bugs normales o de las vulnerabilidades aisladas en una función concreta. Estamos entrando en una etapa en la que el objetivo principal es la cadena de suministro del software:
- npm
- PyPI
- GitHub Actions
- Docker
- CI/CD
La lógica del atacante es evidente: comprometer una librería popular o un punto central del pipeline da acceso potencial a miles o millones de máquinas de desarrolladores y organizaciones.
Y por eso este problema no es solo de seguridad ofensiva. También es un problema de cultura de desarrollo, higiene operativa y disciplina técnica.
Conclusión
La confianza implícita con la que hemos tratado durante años a muchas dependencias ya no es suficiente. El ecosistema sigue siendo útil, potente y productivo, pero exige una postura más defensiva.
Si trabajas con JavaScript hoy, no basta con que tu código esté bien. También necesitas saber qué instalas, quién lo publica, qué ejecuta en tu máquina y cómo se comporta tu cadena de dependencias.
Fuentes
- Cybernews: Hundreds of NPM packages compromised in a new supply chain attack
- Google Cloud: North Korea-nexus threat actor targets Axios npm package
- arXiv: Original Sin of npm: A Study on Vulnerability Propagation in JavaScript Dependency Networks
- BleepingComputer: Shai-Hulud attack ships signed malicious TanStack, Mistral npm packages