system onlinepath: /guias/hacking/ataques-de-cadena-de-suministro/mode: knowledge_baselocal:
Hacking ético · Nivel intermedio

Ataques de cadena de suministro, dependency confusion y typosquatting

Ninguno de estos ataques necesita vulnerar nada. Aprovechan cómo resuelven nombres los gestores de paquetes, que es una decisión de diseño y no un error. Por eso funcionan tan bien y por eso hay que conocerlos.

12 min de lectura▣ Actualizada el ◇ Por Underc0de
Respuesta rápida

Los ataques a la cadena de suministro entran por el eslabón más débil entre el código y lo que se ejecuta. Tres variantes se repiten. La confusión de dependencias aprovecha que muchos gestores, ante un mismo nombre en un registro interno y en el público, eligen la versión más alta: publicando una versión altísima con el nombre de un paquete interno de la organización, se logra que la instalación traiga la del atacante. La suplantación de nombres registra nombres casi idénticos a los populares y espera un error de tipeo. Y el secuestro de paquete es el peor: una biblioteca legítima publica una versión maliciosa. Lo que los une es que ninguno explota una vulnerabilidad: usan el comportamiento normal del gestor de paquetes.

Ver índice de contenidos
  1. 01Por qué funcionan
  2. 02Confusión de dependencias
  3. 03Suplantación de nombres
  4. 04Secuestro de paquetes
  5. 05El vector que trajo la IA
  6. 06Casos reales
  7. 07Cómo auditar tus dependencias
  8. 08Qué mitiga cada cosa
  9. 09Errores frecuentes
  10. 10Preguntas frecuentes
  11. 11Fuentes

Por qué funcionan

La documentación de SLSA lo plantea con precisión: existe riesgo de modificación del código «en cada eslabón de una cadena de suministro típica de software, desde el origen hasta la compilación, pasando por el empaquetado y la distribución».

Pero la razón por la que estos ataques son tan efectivos es más específica y más incómoda: no explotan errores, explotan decisiones de diseño. Que un gestor de paquetes instale la versión más alta disponible, o que resuelva un nombre en varios registros, no es un fallo: es el comportamiento documentado y deseado. El atacante solo lo usa.

La asimetría que los hace rentables

Atacar una organización requiere estudiarla. Comprometer un paquete que usan cien mil proyectos requiere el mismo esfuerzo y alcanza a cien mil. Por eso el patrón dominante no es el ataque dirigido sino el barrido: publicar algo y esperar. Eso significa que casi nadie es «demasiado chico para que lo ataquen»: nadie te eligió.

Confusión de dependencias

Cómo funcionan los tres ataques principales a la cadena de suministro de software. A la izquierda, la confusión de dependencias: una organización tiene paquetes internos con nombres propios que resuelve contra un registro privado, pero si el gestor está configurado para consultar también el registro público y elige la versión más alta disponible, un atacante que publique en el registro público un paquete con ese mismo nombre interno y un número de versión altísimo logra que la instalación traiga el suyo en lugar del interno; no explota ninguna vulnerabilidad, usa la regla de resolución documentada. Se aclara que la mitigación es fijar el registro por espacio de nombres y reservar los nombres internos en el registro público. Al centro, la suplantación de nombres o typosquatting: se registran nombres casi idénticos a paquetes populares, aprovechando errores de tipeo, guiones cambiados por puntos, singulares por plurales o el nombre de la organización omitido, y se espera que alguien se equivoque al escribir; la mitigación es instalar siempre desde el archivo de bloqueo y revisar en la propuesta de cambio cada dependencia nueva. A la derecha, el secuestro de paquete, que es el más difícil de detectar: una biblioteca legítima y ya auditada publica una versión maliciosa, sea porque robaron la cuenta del mantenedor, porque el proyecto cambió de manos o porque el propio mantenedor lo hizo; el nombre es correcto, el proyecto es el que se quería, y el paquete tiene reputación e historial, así que ninguna revisión de nombre lo detecta. La mitigación es fijar versiones exactas por resumen criptográfico y no actualizar de forma automática y ciega. Abajo, el vector que trajo la inteligencia artificial: un modelo puede sugerir con seguridad el nombre de un paquete que no existe, y si ese nombre inventado se repite alguien puede registrarlo con contenido malicioso, de modo que basta con ocupar el hueco que la herramienta inventó sin necesidad de parecerse a nada legítimo. Al pie, lo que une a los cuatro casos: ninguno explota una vulnerabilidad, todos usan el comportamiento normal del gestor de paquetes, y entran por la puerta que se dejó abierta a propósito, que es la instalación automática de dependencias.
Ninguno explota un fallo. Los cuatro usan el comportamiento documentado del gestor de paquetes.

Es el más elegante de los tres y el que más sorprende cuando se entiende. Se apoya en cómo resuelven los nombres los gestores de paquetes cuando hay más de un registro configurado.

El escenario típico: una organización tiene paquetes internos —digamos facturacion-utils— publicados en un registro privado. El gestor está configurado para buscar ahí y también en el registro público, porque de ahí vienen las dependencias externas. Y ante dos candidatos con el mismo nombre, muchas configuraciones eligen la versión más alta.

text
Registro privado:   facturacion-utils  1.4.2   ← el paquete real
Registro público:   facturacion-utils  99.0.0  ← publicado por un tercero

El gestor consulta los dos, compara y elige la versión más alta.
Resultado: instala el del registro público.

No hubo intrusión. La regla de resolución hizo lo que dice hacer.

Lo que vuelve viable el ataque es que los nombres internos suelen ser descubribles: aparecen en archivos de configuración subidos por error, en repositorios públicos de la organización, en trazas de error de una aplicación, en imágenes de contenedor publicadas o en ofertas de trabajo que enumeran componentes internos.

La mitigación es de configuración: fijar el registro por espacio de nombres —que todo lo que empiece con el prefijo de la organización se busque solo en el registro privado— y, como medida barata, reservar los nombres internos en el registro público para que nadie más pueda publicarlos.

Suplantación de nombres

La variante más simple: registrar nombres casi idénticos a paquetes populares y esperar el error de tipeo. Las formas que se repiten:

  • Letras cambiadas o faltantes: una vocal de más, una consonante duplicada.
  • Guion por punto o por guion bajo: los separadores se confunden todo el tiempo.
  • Singular por plural: request y requests son nombres distintos.
  • El espacio de nombres omitido: el paquete real pertenece a una organización y el falso no.
  • El nombre del proyecto en lugar del paquete: se llaman distinto más seguido de lo que parece.

Su tasa de éxito individual es baja, y no importa: el costo de publicar es cero y el alcance es todo internet. Además el error no siempre lo comete una persona: aparece en documentación mal escrita, en respuestas copiadas de foros y en scripts de instalación heredados.

La mitigación efectiva no es «escribir con cuidado» sino de proceso: instalar siempre desde el archivo de bloqueo —de modo que una instalación no resuelva nombres de nuevo— y revisar cada dependencia nueva en la propuesta de cambio, donde una línea agregada al archivo de bloqueo es visible para otra persona.

Secuestro de paquetes

El más difícil de detectar, porque el nombre es correcto: el paquete es el que querías, del proyecto que querías, con su historial y su reputación. Lo que cambió es una versión.

Las tres formas en que ocurre:

Formas de secuestro de un paquete legítimo
CómoQué pasa
Cuenta comprometidaRoban las credenciales del mantenedor y publican en su nombre
Cambio de manosEl mantenedor original entrega el proyecto a alguien que se ofreció a ayudar
El propio mantenedorPublica un cambio dañino de forma deliberada

Ninguna revisión de nombres lo detecta, y ahí está la lección incómoda: auditar una dependencia una sola vez no sirve. El riesgo no está en la versión que revisaste, sino en la próxima que se instale.

La mitigación es fijar versiones por resumen criptográfico y no actualizar de forma automática y ciega. Que una actualización pase por una revisión —aunque sea rápida— convierte un incidente silencioso en una decisión.

El vector que trajo la IA

Una variante nueva que conviene conocer porque cambia la superficie. Un asistente de programación puede sugerir, con total seguridad, el nombre de un paquete que no existe. Si ese nombre inventado se repite —y se repite, porque los modelos tienden a los mismos errores— alguien puede registrarlo con contenido malicioso y esperar.

Lo particular del caso es que no necesita parecerse a nada legítimo: basta con ocupar el hueco que la herramienta inventó. No hay error de tipeo que evitar ni nombre parecido que detectar; el nombre está mal desde el origen y suena perfectamente plausible.

La defensa es la disciplina de siempre con un paso más: verificar que cada dependencia sugerida existe, es la que se quería y tiene mantenimiento real, antes de que entre al archivo de bloqueo. El contexto completo está en inteligencia artificial aplicada a pipelines CI/CD.

Casos reales

El blog de Underc0de documenta esta familia con regularidad, y los casos sirven para ver el patrón en lugar de imaginarlo:

Casos documentados y a qué variante corresponden
CasoVariante
Paquetes maliciosos en npm y PyPI que roban credencialesPublicación directa: el vector más simple
Malware en versiones npm de node-ipcSecuestro: un paquete legítimo publica una versión maliciosa
RAT disfrazado de corrector ortográfico en PyPIUtilidad inofensiva: apunta a lo que nadie revisa
Modelo de OpenAI suplantado en Hugging FaceSuplantación en un registro de modelos

El último merece atención porque amplía el terreno: los pesos de un modelo se descargan de un registro público con la misma confianza que un paquete, y son un archivo que se carga y ejecuta. Tratar los modelos como datos y no como software deja esa puerta sin vigilancia.

Cómo auditar tus dependencias

Sobre tus propios proyectos, o con autorización escrita sobre los de un cliente. Cinco comprobaciones concretas:

bash
# 1. El árbol COMPLETO, no solo las directas: ahí está la mayoría del código
npm ls --all
pip list --format=freeze

# 2. Vulnerabilidades conocidas en lo que ya tenés
npm audit
pip-audit

# 3. ¿La instalación respeta el archivo de bloqueo o resuelve de nuevo?
#    Si el pipeline usa 'npm install' en vez de 'npm ci', resuelve de nuevo.
grep -rn 'npm install|pip install' .github/ Jenkinsfile 2>/dev/null

# 4. ¿Hay más de un registro configurado, y con qué prioridad?
npm config get registry
cat .npmrc pip.conf 2>/dev/null

Y la quinta, que es manual y la que más encuentra: revisar los nombres de los paquetes internos y buscarlos en el registro público. Si alguno está libre, ahí hay una confusión de dependencias esperando; si alguno está tomado por un tercero, hay que mirarlo con urgencia.

Las señales de alerta al revisar un paquete concreto: publicado hace muy poco con muy pocas descargas, sin repositorio público asociado, con una versión desproporcionadamente alta, con guiones de instalación que ejecutan código, o con un mantenedor que no tiene otra actividad.

Qué mitiga cada cosa

La tabla que ordena el trabajo, porque no todas las medidas sirven para todas las variantes:

Qué medida mitiga cada variante de ataque
MedidaConfusiónSuplantaciónSecuestro
Archivo de bloqueo respetado en la instalaciónParcialParcial
Registro fijado por espacio de nombresNoNo
Nombres internos reservados en el registro públicoNoNo
Fijado por resumen criptográfico
Revisión de dependencias en cada cambio
Verificación de procedencia y firma

La única columna que se cubre con una sola medida es la de confusión, y es la más barata de cerrar: fijar el registro por espacio de nombres es un archivo de configuración.

Errores frecuentes

  • Creer que se es demasiado chico. Estos ataques son barridos: nadie te eligió.
  • Revisar solo las dependencias directas. El árbol indirecto es donde vive la mayor parte del código.
  • Auditar una dependencia una sola vez. El riesgo está en la próxima versión.
  • Usar la instalación que resuelve de nuevo en el pipeline. Anula el archivo de bloqueo.
  • Tener registro privado y público sin fijar los espacios de nombres. Es la condición exacta de la confusión de dependencias.
  • Suponer que los nombres internos son secretos. Se filtran por configuraciones, trazas y ofertas de trabajo.
  • Aceptar un nombre de paquete que sugirió un asistente sin verificarlo. Puede no existir.
  • Tratar los modelos de IA como datos. Se descargan de registros públicos igual que los paquetes.

Preguntas frecuentes

¿Qué es la confusión de dependencias?

Es un ataque que aprovecha cómo resuelven los nombres los gestores de paquetes cuando hay más de un registro configurado. Si una organización tiene paquetes internos en un registro privado y el gestor consulta también el público, y ante dos candidatos con el mismo nombre elige la versión más alta, entonces publicar en el registro público un paquete con ese nombre interno y una versión altísima hace que la instalación traiga el del atacante. No explota ninguna vulnerabilidad: usa la regla de resolución documentada.

¿Cómo se protege una organización de la confusión de dependencias?

Con dos medidas concretas y baratas. La primera es fijar el registro por espacio de nombres: configurar el gestor para que todo lo que empiece con el prefijo de la organización se busque solo en el registro privado, sin consultar el público. La segunda es reservar esos nombres en el registro público, para que nadie más pueda publicarlos. Ambas son cambios de configuración y cierran la variante por completo, algo que no ocurre con las otras.

¿Por qué el secuestro de un paquete es más difícil de detectar?

Porque el nombre es correcto. El paquete es el que querías, del proyecto que querías, con su historial y su reputación intactos: lo único que cambió es una versión. Puede pasar porque robaron la cuenta del mantenedor, porque el proyecto cambió de manos o porque el propio mantenedor publicó algo dañino. Ninguna revisión de nombres lo detecta, y de ahí la lección: auditar una dependencia una sola vez no sirve, porque el riesgo no está en la versión que revisaste sino en la próxima.

¿Los paquetes internos son secretos?

Casi nunca, y suponer que sí es lo que vuelve viable el ataque. Los nombres internos aparecen en archivos de configuración subidos por error a repositorios públicos, en trazas de error de aplicaciones, en imágenes de contenedor publicadas, en informes de dependencias y hasta en ofertas de trabajo que enumeran los componentes que usa el equipo. Conviene tratarlos como información pública y protegerlos con configuración del gestor de paquetes, no con la esperanza de que nadie los conozca.

¿Qué es el vector que trajo la IA?

Un asistente de programación puede sugerir con total seguridad el nombre de un paquete que no existe, y como los modelos tienden a los mismos errores, ese nombre inventado se repite. Alguien puede registrarlo con contenido malicioso y esperar a que se instale. Lo particular es que no necesita parecerse a nada legítimo: basta con ocupar el hueco que la herramienta inventó, y el nombre suena plausible. La defensa es verificar que cada dependencia sugerida existe y tiene mantenimiento real antes de que entre al archivo de bloqueo.

¿Alcanza con el archivo de bloqueo?

Ayuda mucho y no alcanza solo. El archivo de bloqueo evita que una instalación resuelva nombres de nuevo, así que cubre bien la suplantación de nombres, pero para eso el pipeline tiene que usar el comando que respeta el archivo y falla si no coincide, no el que resuelve otra vez. Contra el secuestro protege solo hasta la próxima actualización, y contra la confusión de dependencias no hace nada si el gestor sigue consultando dos registros. Hacen falta las tres medidas juntas.

Fuentes

Documentación oficial y material de la comunidad consultados para esta guía. Fecha de consulta: 27 de julio de 2026.

Aportes de la comunidad Underc0de

  1. Underc0de, blog. Detectan paquetes maliciosos en npm y PyPI que roban credenciales, 9 de julio de 2026.
  2. Underc0de, blog. Malware detectado en versiones npm de node-ipc, 14 de mayo de 2026. El caso del paquete legítimo que se vuelve malicioso.
  3. Underc0de, blog. Paquetes maliciosos en PyPI distribuyen un RAT disfrazado de corrector ortográfico, 28 de enero de 2026.
  4. Underc0de, blog. Malware en Hugging Face suplanta modelo de OpenAI, 12 de mayo de 2026. El mismo patrón aplicado a registros de modelos.

Documentación oficial

  1. OWASP. A03:2025 Software Supply Chain Failures. La categoría que reconoce esta familia de ataques.
  2. SLSA, Linux Foundation. About SLSA. El riesgo de modificación en cada eslabón, y el marco de niveles.
  3. SLSA. Threats & mitigations. El catálogo de amenazas por eslabón de la cadena.
  4. OWASP. Vulnerable Dependency Management Cheat Sheet. Prácticas de gestión de dependencias.
  5. NIST. Secure Software Development Framework (SSDF), SP 800-218. El grupo de prácticas de protección del software.