TL; DR
Los paquetes se eliminan solos. Durante quince días de agosto, un operador de npm publicó nueve paquetes con nueve nombres diferentes desde siete cuentas y retiró ocho de ellos personalmente. El tiempo que cada paquete permaneció activo se redujo de trece horas a diecisiete minutos. Esta técnica no es exclusiva suya: otros siete paquetes de operadores independientes, con cargas útiles completamente diferentes, fueron retirados por sus propios editores con una media de 37.8 minutos. El archivo desaparece antes de que se ejecuten la mayoría de los procesos de defensa, y la instalación ya se ha realizado.
Todo lo que expone el registro rota; la carga útil no. Los nueve enviaron un byte idéntico bin/ Directorio, los mismos resúmenes SHA-256 en tres nombres de paquetes y dos cuentas, con quince días de diferencia. La identidad del contenido es la única señal de seguimiento que este operador no rompió, y el único paquete que nunca retiró es la razón por la que se pudo examinar todo esto.
Las personas que lo instalan no son víctimas y, de todos modos, están muy expuestas. Esta herramienta no está dirigida a desarrolladores: burla la supervisión remota de exámenes mediante captura de pantalla oculta, extracción de texto en pantalla y respuestas devueltas a una superposición, por lo que quienquiera que se dirija npm install es el beneficiario previsto, no el objetivo. También ejecutan un binario sin firmar que descifra las cookies de su navegador, desde una cuenta que se elimina automáticamente en menos de una hora. No pueden recibir una solución, no pueden auditar posteriormente lo que ejecutaron y no pueden informar de los daños sin revelar el motivo de su instalación.
Ecosistema: npm, se observa el mismo patrón en PyPI. Período: Junio-agosto de 2026.
La medida
El tiempo de permanencia es el intervalo entre la aparición y la desaparición de un paquete, calculado a partir de los metadatos del propio registro. Se trata de mediciones, no de estimaciones.
| PREMIUM | Publicado (UTC) | De pie |
|---|---|---|
moidev | 2026-08-16 16:31 | 5h 58m |
moidevx | 2026-08-17 03:24 | 13h 23m |
moidevz | 2026-08-26 03:38 | 12h 56m |
moideva | 2026-08-26 18:58 | 1h 33m |
amicat | 2026-08-28 20:48 | 17m |
bmcat | 2026-08-28 21:17 | 47m |
eyevox | 2026-08-28 21:44 | 21m |
moidevh | 2026-08-31 03:22 | 47m |
Leídas en orden de publicación, la ventana se reduce en más de cuarenta veces: de 13 horas y 23 minutos en su punto máximo a 17 minutos en su punto mínimo. Los primeros cuatro paquetes tienen una duración promedio de ocho horas y media; los últimos cuatro, de treinta y tres minutos. El 28 de agosto, se publicaron y retiraron tres paquetes en un lapso de tan solo 77 minutos.
La contracción no es una deriva gradual. Se concentra entre el 26 y el 28 de agosto, y lo que cambió fue la estimación del operador sobre cuánto tiempo puede permanecer un paquete en pie de forma segura.
Cada retiro aquí es iniciado por el editor. El documento de registro para cada uno muestra una lista de mantenedores vacía junto a un tiempo.inédito registro: la firma de una publicación no publicada en lugar de una eliminación. Un noveno paquete, eyioussNunca se retiró en absoluto; esa es la razón por la que todo esto pudo ser examinado.
Existe un segundo régimen de retirada que no debe confundirse con este. Donde solo el versión de carga útil Se retira y el paquete sobrevive, la mediana es de aproximadamente 73 horas en 31 paquetes. Esos reemplazos llegan en lotes programados y dejan un cascarón vacío: un package.json declarando un principal que no envía ningún archivo, cuya única función es mantener el nombre reservado. Ese sistema es una tarea de mantenimiento programada. Este es una ventana de exposición ajustada.
¿Qué sobrevive a la eliminación?
Nueve de estos paquetes pertenecen a un mismo operador: moidev, moidevx, moidevz, Moideva, moidevh, amigo, bmcat, ojo y eyiouss. Los nombres no comparten ninguna convención: cualquiera que esté siguiendo el moidev Stem se habría perdido más de la mitad de ellos, y fueron publicados desde siete cuentas diferentes, casi todas registradas en dominios de correo electrónico desechables.
Lo que tienen en común es una entrada manifiesta sin razón de ser:
"papelera": { "": "bin/kalamasha-tool.js" } } Conservamos copias de cinco antes de su eliminación. En los cinco, el total compartimiento/ El directorio es idéntico byte a byte:
| Archivo | SHA-256 |
|---|---|
bin/kalamasha-tool.js | 0c293be90c10c8a7618d25f4c4811fa63612b7bc5199b86e10bb31eb36c716dd |
bin/uia_extract.exe | e2fda5aa8397799669f29258f69e803cf05d322c1d93269eef6754ca024c3865 |
bin/chrome_cookies.ps1 | 21b61ec810331850d72423c40c5448e6cd310c4cfad6aed54f92cd7e7cac5f3a |
bin/stealth_capture.ps1 | c9baf5897c03b941c54f736df5af9243ad28794a9e69746d41d4f4a34065589c |
bin/uia_extract.py | c20b38c63efd9221930095c54b42cdd5adffa1972c44c4578226cbe1e4dbac3e |
bin/uia_get_text.ps1 | 4a3f3ada0bdf13aa8e89edb8af817c7816296147dae5be25f169ff960d28a87c |
Dos señales adicionales coinciden. Tres de los paquetes se publicaron a las 03:24, 03:38 y 03:22 UTC del 17, 26 y 31 de agosto, respectivamente; un intervalo de dieciséis minutos a lo largo de quince días y en tres cuentas distintas. Además, dos de esas cuentas estaban registradas en el mismo dominio de correo electrónico desechable, lo que las vincula independientemente del código.
Las cuentas
Estas son las cuentas de editores de npm que distribuyeron la carga útil, con el paquete que cada una subió y cuánto tiempo permaneció activo:
| Cuenta de editor | PREMIUM | Dominio de correo electrónico | De pie |
|---|---|---|---|
letol39119 | moidev:1.0.0 | hutdot.com (desechable) | 5h 58m |
so1d1a7i27 | moidevx:1.0.0 | ogzmail.com (desechable) | 13h 23m |
lololololol435678 | eyiouss:3.0.21, 3.0.22, 4.0.1 | ogzmail.com (desechable) | aún publicado |
tagadob568 | moidevz:1.0.0 | ebflyai.com (desechable) | 12h 56m |
tayihim489 | moideva:1.0.0 | prodbits.com (desechable) | 1h 33m |
sahihai123 | amicat:1.0.0, bmcat:2.0.9, eyevox:1.0.0 | correo web del consumidor | 17m / 47m / 21m |
heytoshan | moidevh:1.0.0 | correo web del consumidor | 47m |
so1d1a7i27 y lololololol435678 compartir la ogzmail.com dominio de registro: el vínculo que une la cuenta que aún aloja una copia activa con la cuenta que publicó bajo el dominio de registro: el enlace que vincula moidev brote dos semanas antes. sahihai123 Publicaron y retiraron tres nombres de paquetes distintos en un lapso de 77 minutos el 28 de agosto. heytoshan registrado, publicado moidevhy la retiró 47 minutos después; sigue siendo la única publicación de ese relato.
Ninguna de estas cuentas tiene correo electrónico verificado, ni enlace de control de versiones verificado, ni ha publicado ningún proyecto ajeno a la plataforma. Seis de las siete ya no alojan ningún contenido.
Un paquete nunca fue retirado. eyiouss:4.0.1 Publicado desde el 16 de agosto, aún era recuperable al momento de escribir esto. Ocho artefactos resultaron irrecuperables; la campaña se reconstruyó por completo a partir del único que se conservó. Un operador que borra por reflejo, eventualmente, dejará uno en pie.
Qué hace la herramienta
eyiouss:4.0.1 En npm se describe a sí misma como una "utilidad DOM de alto rendimiento y un puente de diagnóstico para aplicaciones web modernas". Es una herramienta de captura de pantalla y recuperación de respuestas diseñada para funcionar bajo la supervisión remota de exámenes, y así lo afirma el propio código fuente.
El lanzador copia el entorno de ejecución de Electron con un nombre de archivo falso antes de ejecutarlo, y especifica qué es lo que está evitando:
// 🛡️ NOMBRE DEL BINARIO OCULTO: ¡NO debe entrar en conflicto con el Testpad real! const STEALTH_NAME = 'SearchApp.exe';
El encabezado del mismo archivo lo llama Vigilante fantasma anti-Proctor e implementa un bucle de reaparición que retrocede aún más cuanto más rápido se elimina. En otro lugar, el proceso aumenta su propia prioridad. para combatir la limitación de CPU en la supervisión, desplaza la aplicación de examen fuera del primer plano cuando toma el foco y finaliza un proceso secundario de Safe Exam Browser con taskkill /F /T.
La captura se realiza mediante un script de PowerShell incluido, invocado con la política de ejecución deshabilitada y la ventana oculta, mientras que el texto en pantalla se recopila en paralelo a través de la automatización de la interfaz de usuario de Windows. Las imágenes y el texto en cola se envían a una sesión de modelo de lenguaje en un navegador integrado y la respuesta se muestra en una superposición siempre visible. Esta conexión se pospone deliberadamente, y el código explica el motivo: para evitar la exposición permanente a NETSTAT.
El paquete también se envía chrome_cookies.ps1, encabezado EXTRACTOR DE COOKIES DE CHROME, que descifra las cookies de Chrome y Edge a través de DPAPI y lee la base de datos de cookies de hasta cuatro perfiles de navegador. Indicado previamentecisely: No encontramos ese script invocado por su nombre desde ningún archivo JavaScript distribuido. Lo que sí está presente y accesible es la parte que lo consume, la cual inyecta las cookies de sesión almacenadas en el navegador integrado.
La posición de las personas que lo instalan
Nadie instala esto por accidente. No tiene ninguna función fuera de un examen supervisado, y su resultado es una superposición de respuestas en la propia pantalla del usuario. La descripción engañosa del paquete no está dirigida en absoluto al instalador, sino que es una tapadera dirigida al registro y a cualquiera que audite la máquina posteriormente. El instalador sabe lo que está obteniendo; la descripción existe para que grabar de la instalación no lo refleja.
Las partes perjudicadas son terceros que nunca tuvieron relación con npm: la institución que administra el examen, los demás candidatos y todos aquellos que, posteriormente, dependen de que la credencial tenga algún significado.
Pero, por lo tanto, el instalador no está a salvo, y esta es la parte que vale la pena destacar, porque el modelo de paquete efímero es precisamente lo que crea el riesgo.
Están ejecutando un binario sin firmar de nadie. uia_extract.exe barcos compilados, sin fuente ni procedencia de compilación, de una cuenta que ya no existe. El mismo archivo, por hash, ha sido republicado por letol39119, so1d1a7i27, lololololol435678, tagadob568, tayihim489, sahihai123 y heytoshan En quince días. No hay ningún responsable a quien preguntar, ningún repositorio que consultar y ningún historial que revisar: cada usuario que lo envió se eliminó a sí mismo.
Le han otorgado precisamente las capacidades que necesita el malware. Un proceso oculto, que se ejecuta con un nombre falso, descifra el almacenamiento de cookies del navegador, lee la pantalla continuamente, desactiva el software de seguridad y se reinicia al ser interrumpido. Actualmente, el descifrado de cookies se limita a los dominios de un proveedor y se realiza en la sesión del usuario. Este cambio de ámbito se realiza con una sola línea de código, y si se modificara, no se detectaría ningún cambio en el modelo de entrega: un nuevo nombre, una nueva cuenta o una nueva carga de archivos.
No pueden recibir una solución. El paquete se retira de la plataforma en menos de una hora. No hay ruta de actualización, ni aviso, ni forma de saber después que la versión que instalaron era diferente a la que instaló su amigo. Lo que esté en el equipo se queda ahí.
No pueden auditar lo que ejecutaron. Su archivo de bloqueo ahora hace referencia a un paquete que ya no se resuelve. Si posteriormente quisieran determinar qué hay en su máquina —tras un incidente o una disputa—, el registro no tendría ningún registro que proporcionarles.
Y no pueden denunciar los daños. Un usuario afectado por esta herramienta no puede presentar un informe de abuso sin revelar el motivo de su instalación. Esto no es casual. Los informes de abuso del registro son un canal principal para detectar paquetes de corta duración, y la base de usuarios de este operador es estructuralmente incapaz de utilizarlo. El único adversario restante es el escaneo automatizado, para el cual se ha calibrado una ventana de diecisiete minutos.
La estructura de la víctima y el tiempo de permanencia son el mismo hecho que se repite. Esto también explica la anomalía en la cronología: si la retirada se debiera al temor a las quejas, el paquete popular y de larga duración se habría retirado primero. No fue así, porque las quejas nunca llegaron.
El mismo patrón, un operador diferente
El operador supervisor no es el único en esto, y la ejecución paralela más clara se realiza sobre una carga útil no relacionada.
Entre el 24 y el 27 de agosto, aparecieron cuatro paquetes npm con nombres tomados de herramientas de autenticación de dos factores. autenticación-otp, Secretokey-2fa, Secretokey2fa y Clave secreta de autenticación de dos factores — que contenían dieciséis versiones entre ellas. Cada una fue publicada desde su propia cuenta recién registrada (beayilol, jeanpaul686g, zzzalipay, dluuuuu), todos sin verificar por correo electrónico, ninguno con un enlace de control de versiones verificado, ninguno publicando nada más. Todos fueron retirados por su propio editor.
La carga útil no tiene nada que ver con el software de examen. Lee los almacenes de credenciales del navegador y los tokens de Discord, y recorre una escalera de autenticación de Xbox Live contra el lanzador de Minecraft para capturar un token de actualización. Aquí el instalador is la víctima en el sentido ordinario, que es lo que hace útil la comparación, porque el comportamiento de entrega es idéntico en ambos casos.
Los cuatro ciclos se ejecutaron en orden de publicación a los 274.9, 37.8, 37.6 y 35.7 minutos: un primer intento prolongado, seguido de una convergencia hacia una cifra que se mantiene. Otros tres paquetes pertenecen a otros operadores y muestran el mismo comportamiento de retirada.
| PREMIUM | Operador | De pie |
|---|---|---|
octopus-action | baliza de reconocimiento | 2.5 min |
mt-ts-serverless-starter | baliza de reconocimiento | 9.6 min |
2fa-Secretokey | Nombres de portada de 2FA | 35.7 min |
Secretokey2fa | Nombres de portada de 2FA | 37.6 min |
Secretokey-2fa | Nombres de portada de 2FA | 37.8 min |
auth-otp | Nombres de portada de 2FA | 274.9 min |
hex-encode-utils | otros | 724.2 min |
Siete paquetes, con una duración media de 37.8 minutos, ninguno de ellos relacionado con software para exámenes.
Tres cargas útiles no relacionadas, tres conjuntos de cuentas no relacionadas, una técnica compartida.
¿Por qué se está cerrando la ventana?
Algo cambió en el entorno del registro durante 2026, y la explicación más obvia es que el escaneo se volvió más rápido.
Hasta hace poco, los paquetes maliciosos se detectaban principalmente a posteriori: cuando un usuario lo notaba, mediante un informe posterior o mediante un barrido periódico. La latencia de detección se medía en días. Ese ya no es el único método. Análisis casi en tiempo real de paquetes recién publicados: Alerta temprana de malware de Xygeni Entre un conjunto cada vez mayor de sistemas similares en toda la industria, este reduce considerablemente el tiempo entre la publicación y la inspección.
Un operador que se enfrenta a esta situación tiene dos opciones: dificultar el reconocimiento de la carga útil o reducir el tiempo durante el cual está disponible para su consulta. La segunda opción es más económica, no requiere ingeniería y el registro proporciona el mecanismo de forma gratuita: dentro del plazo de 72 horas para la eliminación de paquetes de npm, un editor puede eliminar un paquete unilateralmente, y el nombre puede reutilizarse posteriormente. La eliminación no tiene ningún coste para el operador.
El momento es el adecuado. Ambos operadores anteriores convergen en una cifra y la mantienen en lugar de desviarse, que es como se ve un parámetro ajustado, no una cuestión de conveniencia. Y el parámetro en el que convergieron —decenas de minutos— se sitúa precisely donde tendría que ubicarse para superar una inspección automatizada y, al mismo tiempo, permitir que el paquete se pudiera instalar el tiempo suficiente para llegar a su público.
Esto sigue siendo una hipótesis. Los datos de sincronización no permiten diferenciar una respuesta al escaneo de una respuesta a la aplicación del registro, ni de la maduración operativa ordinaria a medida que estos operadores aprenden unos de otros. Lo que se puede afirmar sin inferencias es más limitado y, aun así, útil: El plazo de exposición es ahora tan corto que cualquier control que dependa de la inspección de un paquete después de su publicación está compitiendo contra el reloj que establece el operador. Los controles que no dependen de la inspección —como la cuarentena por antigüedad o la desactivación de los scripts de instalación— no se ven afectados por esa condición de carrera, lo cual es la razón práctica para preferirlos.
Qué hacer al respecto
Cuarentena por edad. Ninguna de las dependencias registradas en la tabla de tiempo de permanencia sobrevivió trece horas. Una política que impidiera la instalación de cualquier versión de una dependencia hasta que hubiera existido durante 72 horas las habría excluido todas sin detectar nada.
Deshabilitar los scripts de instalación por defecto. –ignorar-scripts Elimina el mecanismo de entrega del que dependen los paquetes de robo de credenciales en este corpus. No ayuda contra una herramienta que el usuario ejecuta deliberadamente, que es precisla distinción que vale la pena comprender.
Tratar la desaparición como un incidente de seguridad. Alerta cuando una dependencia instalada deja de resolverse. La evidencia aún reside en tu archivo de bloqueo, no en el registro.
Rastrea el contenido, no los nombres. Los seis resúmenes anteriores coinciden independientemente del nombre del paquete, la cuenta del editor o la cadena de versión; este operador demostró que todos los campos cambian. Una regla del registro que establezca que una cuenta recién registrada que retira su único paquete en una hora es un patrón que debe reportarse se habría activado en todos los paquetes, basándose únicamente en los metadatos.
Y si estás considerando instalar algo en esta categoría: Las propiedades que dificultan la detección por parte del registro son las mismas que te dejan sin posibilidad de reclamación. No hay ningún editor al que responsabilizar, ninguna ruta de actualización y ningún registro de lo que ejecutaste.
indicadores
| Tipo | Valor |
|---|---|
| Archivo | bin/kalamasha-tool.js — no-standard punto de entrada del contenedor |
| SHA-256 | 0c293be90c10c8a7618d25f4c4811fa63612b7bc5199b86e10bb31eb36c716dd |
| SHA-256 | e2fda5aa8397799669f29258f69e803cf05d322c1d93269eef6754ca024c3865 |
| Proceso | SearchApp.exe escrito junto a un entorno de ejecución Electron legítimo |
| Comportamiento | powershell -ExecutionPolicy Bypass -File con windowsHide: true |
| Comportamiento | taskkill /F /T dirigido a un proceso de navegador de examen seguro |
| metadatos | Lista de mantenedores vacía junto a una time.unpublished grabar |
| Cuentas | letol39119, so1d1a7i27, lololololol435678, tagadob568, tayihim489, sahihai123, heytoshan |
| Registración de | ogzmail.com, hutdot.com, ebflyai.com, prodbits.com — dominios de correo desechable |
Referencias
- Política de despublicación de npm — el plazo de 72 horas dentro del cual un editor puede retirar un paquete sin intervención.







