# Ataques de cadena de suministro, dependency confusion y typosquatting

**Categoría:** Hacking ético · **Nivel:** Intermedio · **Lectura:** 12 min
**Publicada:** 2026-07-27 · **Actualizada:** 2026-07-27 · **Autoría:** Underc0de
**Versión HTML (canónica):** https://underc0de.org/guias/hacking/ataques-de-cadena-de-suministro/

## 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.

## 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

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:

| Cómo | Qué pasa |
|---|---|
| **Cuenta comprometida** | Roban las credenciales del mantenedor y publican en su nombre |
| **Cambio de manos** | El mantenedor original entrega el proyecto a alguien que se ofreció a ayudar |
| **El propio mantenedor** | Publica 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](../../devops-cloud/inteligencia-artificial-en-pipelines-ci-cd/index.md).

## Casos reales

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

| Caso | Variante |
|---|---|
| [Paquetes maliciosos en npm y PyPI que roban credenciales](https://blog.underc0de.org/detectan-paquetes-maliciosos-en-npm-y-pypi-que-roban-credenciales/) | Publicación directa: el vector más simple |
| [Malware en versiones npm de node-ipc](https://blog.underc0de.org/malware-detectado-en-versiones-npm-de-node-ipc/) | **Secuestro**: un paquete legítimo publica una versión maliciosa |
| [RAT disfrazado de corrector ortográfico en PyPI](https://blog.underc0de.org/paquetes-maliciosos-en-pypi-distribuyen-rat-disfrazado-de-corrector-ortografico/) | Utilidad inofensiva: apunta a lo que nadie revisa |
| [Modelo de OpenAI suplantado en Hugging Face](https://blog.underc0de.org/malware-en-hugging-face-suplanta-modelo-de-openai/) | Suplantació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:

| Medida | Confusión | Suplantación | Secuestro |
|---|---|---|---|
| Archivo de bloqueo respetado en la instalación | Parcial | **Sí** | Parcial |
| Registro fijado por espacio de nombres | **Sí** | No | No |
| Nombres internos reservados en el registro público | **Sí** | No | No |
| Fijado por resumen criptográfico | Sí | Sí | **Sí** |
| Revisión de dependencias en cada cambio | Sí | **Sí** | Sí |
| Verificación de procedencia y firma | Sí | Sí | **Sí** |

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.

> El tratamiento defensivo completo —procedencia con SLSA, inventario con SBOM, firma con Sigstore y verificación en el momento de admitir— está en [seguridad de la cadena de suministro de software](../../devops-cloud/seguridad-de-la-cadena-de-suministro-de-software/index.md). Esta guía explica el ataque; esa, los controles. Y para el encuadre de trabajo autorizado, [fundamentos de hacking ético](../fundamentos-hacking-etico/index.md).

## 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](https://blog.underc0de.org/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](https://blog.underc0de.org/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](https://blog.underc0de.org/paquetes-maliciosos-en-pypi-distribuyen-rat-disfrazado-de-corrector-ortografico/), 28 de enero de 2026.
4. **Underc0de, blog.** [Malware en Hugging Face suplanta modelo de OpenAI](https://blog.underc0de.org/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](https://owasp.org/Top10/2025/A03_2025-Software_Supply_Chain_Failures/). La categoría que reconoce esta familia de ataques.
2. **SLSA, Linux Foundation.** [About SLSA](https://slsa.dev/spec/v1.2/about). El riesgo de modificación en cada eslabón, y el marco de niveles.
3. **SLSA.** [Threats & mitigations](https://slsa.dev/spec/v1.2/threats). El catálogo de amenazas por eslabón de la cadena.
4. **OWASP.** [Vulnerable Dependency Management Cheat Sheet](https://cheatsheetseries.owasp.org/cheatsheets/Vulnerable_Dependency_Management_Cheat_Sheet.html). Prácticas de gestión de dependencias.
5. **NIST.** [Secure Software Development Framework (SSDF)](https://csrc.nist.gov/Projects/ssdf), SP 800-218. El grupo de prácticas de protección del software.

## Guías relacionadas

- [Defensa: SLSA, SBOM y firma](../../devops-cloud/seguridad-de-la-cadena-de-suministro-de-software/index.md)
- [OWASP Top 10 2025](../owasp-top-10-2025-explicado/index.md)
- [Fundamentos de hacking ético](../fundamentos-hacking-etico/index.md)
- [WordPress y complementos](../../desarrollo-web/wordpress-desde-cero/index.md)
- [Índice de Hacking ético](../index.md)
