En julio de 2025, estaba creando un prototipo para un nuevo proyecto y decidí probar MikroORM. La documentación decía que había que ejecutar npx mikro-orm-esm para las migraciones. Así lo hice.
npm ERR! código E404
npm ERR! 404 No encontrado - GET https://registry.npmjs.org/mikro-orm-esmEl paquete no existe, ¡qué raro! Entonces se me ocurrió: ¿y si alguien lo hubiera registrado? Lo habría visto:
Es necesario instalar los siguientes paquetes:
mikro-orm-esm@1.0.0
¿Desea continuar? (y)Simplemente habría golpeado. y. Todo el mundo lo hace. Y nada en ese mensaje te indica si estás a punto de instalar malware o una herramienta legítima.
Los documentos apuntaban a un paquete inexistente. ¿Cuántas otras referencias phantom hay por ahí? ¿Cuántas ya han sido reclamadas por los atacantes? Tenía que saberlo.
Así que empecé a investigar. Escribí scripts para escanear npm en busca de paquetes referenciados en READMEy guiones, pero nunca se publicaron. Se cotejaron miles de npx Invocaciones. Encontré docenas. Reclamé 14 de ellas antes de que nadie más pudiera hacerlo. Entonces ocurrió S1ngularity y la investigación quedó archivada.
Seis meses después, la comunidad que investigaba temas similares me recordó mi investigación. Finalmente comprobé el número de descargas: ¡121 539 descargas!
La gente había estado ejecutando estos comandos inexistentes miles de veces a la semana. Durante meses. Mientras los paquetes permanecían allí recopilando datos.
Seis meses de datos
Las descargas no se mantuvieron estables, sino que aumentaron. Comenzaron lentamente a finales de julio. El pico más reciente alcanzó las 4236 descargas en un solo día (16 de enero de 2026).
- Total: 121 539 descargas en 128 paquetes.
- Media semanal: 3903
- Día pico: 4236 descargas (16 de enero de 2026)
Nota rápida sobre el ruido: cada vez que publicas una nueva versión de un paquete, automáticamente recibe entre 60 y 100 descargas de escáneres de seguridad y servidores espejo. Ese es el ruido básico por lanzamiento. Los paquetes con múltiples versiones acumulan ruido rápidamente. Cualquier cosa que supere constantemente ese umbral es uso real.
¿Te das cuenta de la caída a finales de diciembre? Son las vacaciones. Incluso las descargas phantom se toman vacaciones en Navidad.
Los tres grandes
Tres paquetes representan el 79 % de todas las descargas:
generador-de-api-abierto-cli: 48 356 descargas (paquete real: @openapitools/openapi-generator-cli)cucumber-js: 32 110 descargas (paquete actual:@pepino/pepino)depcruise: 15 637 descargas (paquete real:dependencia-crucero)
generador-de-api-abierto-cli registró 3994 descargas solo en los últimos 7 días. Eso significa que casi 4000 veces alguien intentó ejecutar un comando que no existe. En una semana.
La larga cola
Los paquetes restantes con descargas significativas:
jsdoc2md: 4.641 descargasgrpc_herramientas_nodo_protoc: 4.518 descargasvista-media-interruptor: 1166 descargasguía de estilo: 805 descargasmikro-orm-esm: 314 descargaspvbase64: 142 descargasCromwell: 106 descargas
¿Recuerdas esa referencia de 60-100 descargas por versión? Un paquete con 3 versiones podría tener entre 180 y 300 descargas de ruido puro. fathym con un total de 83 descargas es probablemente todo ruido. Pero mikro-orm-esm ¿Con 314? Incluso teniendo en cuenta las múltiples versiones, se trata de intentos reales.
guía de estilo Con 805 descargas, eso significa cientos de ejecuciones reales. Podría ser CI/CD ejecutándolo repetidamente. Podrían ser docenas de desarrolladores diferentes. En cualquier caso, es un uso real de un paquete que no debería existir.
Cómo los encontramos
En Aikido gestionamos un espejo completo del registro npm. Analizado cada package.json y README en todo el registro. Extraído npx comandos. Referenciados con lo que realmente está registrado. También buscamos en el buscador de código de GitHub para ver cuán extendidos están estos phantom en la práctica, en documentación, configuraciones de CI, scripts, cualquier lugar donde los desarrolladores puedan hacer referencia a ellos.
Tres puntos de datos para cada paquete:
- Referencias en el registro: ¿Cuántos paquetes npm mencionan este comando en su package.json o README?
- Resultados de GitHub: ¿Cuántos archivos de código o repositorios hacen referencia a este comando en GitHub?
- Descargas: ¿Cuántas veces la gente intentó ejecutarlo realmente?
En julio de 2025 reclamamos 14. Cuando retomé la investigación en enero, ampliamos nuestro análisis y encontramos muchos más. En este momento, hemos reclamado un total de 128 paquetes.
Algunos patrones dignos de mención:
Principales vectores de ataque (más de 10 000 descargas): generador-de-api-abierto-cli, cucumber-js, y depcruise Todos muestran una fuerte correlación entre las referencias npm, las menciones en GitHub y las descargas reales. Esto sería devastador en manos de un atacante.
Alta exposición, baja conversión: guía de estilo tiene 246 referencias npm y 286 resultados en GitHub, pero solo 805 descargas. git-scripts-pre-push tiene 126 referencias, pero solo 93 descargas. La visibilidad no siempre equivale a la ejecución.
Vectores solo para documentación: mikro-orm-esm No tiene ninguna referencia en el paquete npm, pero cuenta con 80 resultados en GitHub y 314 descargas. Esto demuestra que la documentación por sí sola puede generar cientos de instalaciones, incluso sin ninguna referencia en el ecosistema npm.
Por qué es peligroso
El ataque es sencillo.
Un atacante registra el paquete. Añade un postinstall Script que extrae variables de entorno: tokens npm, credenciales en la nube, claves API, cualquier cosa que haya por ahí. Luego espera.
En el peor de los casos, eso supone potencialmente unas 4000 máquinas comprometidas por semana. Estaciones de trabajo de desarrolladores. Servidores CI. Entornos de compilación. Es posible que muchos funcionen con credenciales en variables de entorno. No es necesario recurrir al phishing. No hay compromiso de la cadena de suministro de los paquetes existentes. Solo hay que reclamar el nombre y esperar a que npx te traiga a las víctimas.
Cuando alguien ejecuta el comando, ve lo siguiente:
Es necesario instalar los siguientes paquetes:
openapi-generator-cli@1.0.0
¿Desea continuar? (y)El mensaje no muestra quién lo ha publicado. No muestra cuándo. No muestra si es lo que estás buscando. Es posible que veas este mensaje con frecuencia en herramientas legítimas. La memoria muscular toma el control, porque somos humanos. Escribes y, como hacen todos los demás. Eso es todo. Ese es todo el ataque.
Hemos cerrado 128 brechas en múltiples rondas. Hemos detectado los peores casos. Pero hay una larga cola de miles.
Una nota sobre las protecciones de npm
npm cuenta con protección contra el typosquatting. Cuando intentamos reclamar ciertos nombres, npm los rechazó por errores de similitud. Nombres como rsbuild, vuedoc, napi, t-ci eran demasiado parecidos a paquetes ya existentes. Eso es bueno. Significa que npm está bloqueando activamente los intentos evidentes de apropiación indebida.
Pero estos phantom no son errores tipográficos. Son nombres que nunca se registraron en primer lugar. La comprobación de similitud de npm no los detecta porque no hay nada con lo que sean «similares».
Lo que debes hacer
Utiliza npx --no-install
npx --no-install tu-comandoEsto obliga a npx a utilizar únicamente binarios locales. Sin recurrir al registro. Si no está instalado, falla. Eso es lo que quieres.
Instalar las herramientas CLI explícitamente. No confíes en npx para ir a buscarlos:
{
"devDependencies": {
"@openapitools/openapi-generator-cli": "^2.7.0"
}
}
Verifique antes de ejecutar. La documentación dice que hay que ejecutar npx ¿Algo? Comprueba primero que el paquete realmente existe. Comprueba que sea el correcto. Especialmente en CI/CD.
Reclame su espacio de nombres. Si mantiene una herramienta CLI, registre los alias y errores ortográficos obvios. Es una forma económica de asegurarse de que nadie más lo haga con malas intenciones.
Cómo saber si estás afectado
Si eres usuario de Aikido, comprueba tu feed central y filtra los problemas de malware. Cualquier vulnerabilidad phantom aparecerá como un problema crítico 100/100 en el feed. Aikido vuelve a escanear tus repositorios cada noche, aunque recomendamos activar también un escaneo completo.
Si aún no eres usuario de Aikido, crea una cuenta gratuita y conecta tus repositorios. Nuestra cobertura contra malware patentada está incluida en el plan gratuito (no se requiere tarjeta de crédito).
Para protegerse en el futuro, considere utilizar Aikido SafeChain (código abierto), un envoltorio seguro para npm, npx, yarn y pnpm. SafeChain se integra en sus flujos de trabajo actuales, interceptando los comandos de instalación de paquetes y verificándolos con Aikido Intel (nuestra inteligencia de amenazas de código abierto) antes de que lleguen a su máquina. Detenga las amenazas en la puerta.
Las matemáticas
121 539 descargas en siete meses. Una media de 3903 por semana. Pico de 4236 en un solo día. 128 paquetes reclamados en total (14 en julio, el resto en enero).
El ecosistema npm cuenta con millones de paquetes. Los desarrolladores ejecutan comandos npx miles de veces al día. La diferencia entre «predeterminado conveniente» y «ejecución de código arbitrario» es un nombre de paquete sin reclamar.
Protege tu software ahora.




