El malware de npm activado en tiempo de ejecución elude las protecciones contra scripts de instalación
Una campaña maliciosa oculta su payload en una función de npm y evade las protecciones de instalación para robar datos y usar blockchain.
Texto generado por inteligencia artificial, publicado sin revisión humana. Transparencia IA
Imagen ilustrativa generada con IA
Una campaña maliciosa de npm ha trasladado la lógica de ejecución de los hooks de instalación al comportamiento habitual de la biblioteca, lo que permite que los paquetes superen los controles diseñados para bloquear scripts de ciclo de vida peligrosos.
Los investigadores de Checkmarx centraron su investigación en indexed-btree, un paquete diseñado para parecerse a la biblioteca legítima sorted-btree. Según la información publicada sobre los hallazgos de los investigadores, indexed-btree alcanzó aproximadamente dos millones de descargas semanales, lo que generó una exposición considerable en los entornos de desarrollo.
El paquete no depende de preinstall, install ni postinstall. En su lugar, su cargador está oculto dentro de BTree.prototype.set(), una operación normal de B-tree, y se activa durante la ejecución de la aplicación cuando recibe un valor de clave específico.
Este diseño apunta a una brecha entre la seguridad de la instalación y la supervisión en tiempo de ejecución. Un paquete de npm puede instalarse sin solicitar permiso para ejecutar un script de ciclo de vida y, aun así, ejecutar código malicioso más adelante cuando una aplicación llama a las funciones que exporta.
La ruta maliciosa comienza dentro de un método rutinario de la biblioteca
La instalación inicial de indexed-btree parece limpia porque el paquete no utiliza scripts de ciclo de vida de dependencias para lanzar su payload. El comportamiento malicioso comienza únicamente cuando el software que utiliza la biblioteca llama a BTree.prototype.set() con el valor de activación necesario.
No se ha revelado la clave exacta que actúa como activador. Tampoco se han revelado las versiones afectadas del paquete, lo que dificulta delimitar el alcance mediante inventarios en las organizaciones que conservaron varias versiones en cachés de paquetes o lockfiles.
Una vez activado, el método invoca sharedLoad.min.js, que contiene un payload ofuscado de primera fase. Al colocar este cargador dentro de una operación de estructura de datos utilizada con frecuencia, resulta más fácil ocultarlo entre código que parece coherente con la finalidad anunciada del paquete.
Checkmarx evaluó la técnica como capaz de eludir muchos escáneres estáticos y sistemas convencionales de análisis de taint. Estas herramientas pueden inspeccionar hooks de instalación, la creación de subprocesos sospechosos o flujos evidentes desde entradas no confiables hasta funciones peligrosas. En este caso, la rama maliciosa está oculta dentro de una API aparentemente legítima y permanece inactiva hasta que se cumplen determinadas condiciones de ejecución.
Los operadores también construyeron una apariencia más amplia de legitimidad alrededor del paquete. Crearon un repositorio convincente en GitHub, lo llenaron con un historial de commits diseñado para parecer auténtico y mantuvieron una cuenta de desarrollador cuidada. Estas señales pueden influir tanto en los sistemas automatizados de reputación como en los desarrolladores que realizan una revisión manual rápida.
Los controles de npm v12 no cubren la ejecución normal en tiempo de ejecución
En junio de 2026, GitHub anunció medidas de seguridad para npm destinadas a abordar los ataques a la cadena de suministro que habían afectado reiteradamente a los ecosistemas de código abierto desde finales de 2025. Entre esas medidas, npm v12 bloquea los scripts de ciclo de vida de las dependencias, salvo que el usuario los autorice explícitamente.
Las protecciones también restringen la obtención automática de dependencias desde repositorios Git o URL remotas sin permiso. Estos cambios reducen la eficacia de los paquetes que se ejecutan inmediatamente durante la instalación o descargan código externo mediante declaraciones de dependencias.
indexed-btree evita por completo ese límite de seguridad.
Como su cargador malicioso forma parte de la ruta normal de ejecución del paquete, npm no encuentra ningún script de instalación que requiera aprobación. Por tanto, la instalación puede finalizar sin mostrar la advertencia ni solicitar el paso de autorización que los defensores podrían esperar de un paquete malicioso convencional.
Esto no indica que npm v12 haya sido eludido mediante una vulnerabilidad de software. Más bien, pone de manifiesto los límites de un control centrado en una sola fase de ejecución. Las restricciones sobre los scripts de ciclo de vida pueden impedir comportamientos no autorizados durante la instalación, pero no pueden determinar si todas las funciones invocables de una dependencia son seguras.
Por tanto, una instalación correcta y sin advertencias no demuestra que el código instalado sea benigno.
El reconocimiento conduce a un payload cifrado en la blockchain
Tras activarse, el malware realiza un inventario del host. La información recopilada incluye:
- Arquitectura del sistema
- Nombre del host
- Detalles de la CPU
- Información de la memoria
- Tiempo de actividad del sistema
Exfiltra esos datos a través de canales de Slack y Telegram codificados en el malware. No se han revelado los identificadores concretos de los canales, los destinos ni los indicadores de red.
Para el mando y control, la operación consulta un smart contract de Ethereum desplegado en la red de pruebas Sepolia. Esta arquitectura permite a los operadores almacenar o distribuir material del payload a través de infraestructura blockchain, en lugar de depender exclusivamente de un servidor convencional de mando y control.
El malware utiliza un intercambio de claves X25519 para derivar una clave AES. Después descifra un payload de segunda fase recuperado del smart contract. No se han revelado el contenido ni todas las capacidades de esa segunda fase, por lo que el impacto confirmado no debe extenderse más allá del mecanismo de entrega y ejecución observado.
Los investigadores también identificaron una wallet de Ethereum vinculada a la operación que contenía 109 ETH. No existen pruebas concluyentes de que esos fondos procedieran del robo de criptomonedas o de sistemas comprometidos a través de estos paquetes.
El malware incluye además una función de limpieza controlada por el operador. Cuando se activa, puede eliminar sus archivos y retirar el activador malicioso del código fuente del paquete. Esta capacidad puede hacer que un entorno afectado parezca limpio durante una inspección posterior, especialmente si no se conservaron las telemetrías relevantes de procesos, red y sistema de archivos.
Nueve paquetes relacionados ampliaron el alcance de la campaña
Checkmarx relacionó otros nueve paquetes de npm con la misma operación. Los nueve fueron retirados de npm tras su descubrimiento.
| Paquete | Descargas notificadas |
|---|---|
ordered-kv-index |
448.184 |
btree-leaderboard |
493.685 |
priority-slot-queue |
402.860 |
btree-range-store |
468.092 |
btree-core |
1.951.274 |
btree-time-index |
425.312 |
btree-lru-cache |
372.185 |
neighbor-key-map |
366.019 |
sliding-score-window |
448.024 |
No se ha especificado si indexed-btree fue retirado. Su cifra notificada de aproximadamente dos millones de descargas semanales tampoco debe compararse directamente ni sumarse a los totales de descargas de los demás paquetes, que se presentan como cifras notificadas sin el mismo calificativo semanal.
Las estadísticas de descargas demuestran distribución, no compromiso. No revelan cuántas descargas dieron lugar a instalaciones, cuántas aplicaciones llamaron al método modificado ni cuántas ejecuciones proporcionaron la clave de activación necesaria.
No obstante, los nombres de los paquetes apuntan a casos de uso relacionados con el desarrollo de software que implican índices, colas, cachés, mapas y sistemas de puntuación. La posible exposición incluye estaciones de trabajo de desarrolladores, ejecutores de CI, servidores de compilación y otros sistemas en los que las dependencias de npm se ejecutan con acceso al código fuente o a credenciales.
El riesgo principal va más allá de la elaboración básica del perfil del host
No se ha asignado ninguna puntuación CVSS ni una clasificación de gravedad del proveedor. Se trata de una campaña de paquetes maliciosos, no de una vulnerabilidad convencional con un identificador CVE publicado.
Desde el punto de vista operativo, el riesgo es alto porque el código combina una distribución amplia, activación retrasada en tiempo de ejecución, reconocimiento del host, entrega cifrada de un payload de segunda fase y eliminación de evidencias. Un entorno de desarrollo comprometido puede exponer mucho más que los metadatos del sistema recopilados directamente por la primera fase.
En función de los permisos locales, una segunda fase maliciosa podría acceder potencialmente a tokens de publicación de paquetes, credenciales de control de código fuente, claves cloud, secretos de CI, material de firma o configuración de aplicaciones. No se ha confirmado el acceso a estos activos, pero las organizaciones deberían incluirlos al determinar qué estaba disponible para un proceso afectado.
La capacidad de autolimpieza también complica la delimitación del incidente. La ausencia de archivos maliciosos durante el análisis no demuestra que la ejecución no se produjera.
Las organizaciones afectadas deben preservar las evidencias antes de reconstruir los sistemas
Las organizaciones deberían buscar indexed-btree y los nueve nombres relacionados en los inventarios de dependencias, lockfiles, registros internos, cachés de compilación, capas de contenedores y listas de materiales de software. Como se desconocen los rangos de versiones afectados, los investigadores no deberían asumir que una versión concreta es segura sin validar su contenido de forma independiente.
Antes de reconstruir los sistemas, los equipos de respuesta deberían conservar los artefactos de paquetes disponibles, la telemetría de procesos, los historiales de comandos, los registros de red, los registros de CI y las evidencias del sistema de archivos. De lo contrario, el mecanismo de limpieza podría borrar la información necesaria para determinar si se activó el disparador en tiempo de ejecución.
Entre las medidas de respuesta recomendadas se incluyen:
- Aislar los sistemas de desarrollo y compilación potencialmente afectados.
- Rotar todos los secretos accesibles desde esos entornos, incluidas las credenciales de control de código fuente, registros, cloud, despliegue y CI.
- Restaurar desde una copia de seguridad conocida como segura o desde una imagen limpia, en lugar de confiar en el comportamiento de eliminación del propio malware.
- Investigar las conexiones en tiempo de ejecución relacionadas con Slack, Telegram y la infraestructura de Sepolia, teniendo en cuenta que las herramientas legítimas también pueden utilizar esos servicios.
- Buscar intercambios de claves X25519 y actividad de descifrado AES inesperados asociados con Node.js o con procesos de compilación afectados.
- Revisar la ejecución de las aplicaciones, no solo la instalación de paquetes, en busca de llamadas a métodos de biblioteca modificados y de la carga de
sharedLoad.min.js. - Añadir análisis de ejecución en sandbox al proceso de evaluación de paquetes, especialmente cuando las dependencias contengan código ofuscado o modifiquen rutas de API habituales.
El bloqueo de los scripts de ciclo de vida sigue siendo útil, pero solo aborda un punto de la cadena de ejecución de una dependencia. Esta campaña demuestra que los mantenedores maliciosos pueden trasladar la activación a la propia aplicación, donde el código del paquete hereda la confianza y los permisos que ya se han concedido al software normal.
Fuentes
Este artículo es una reelaboración original basada en las siguientes fuentes.
