Skip to main content

Una cuenta olvidada de un colaborador comprometió todo el ámbito de paquetes npm de Mastra

Escrito por
Headshot of Marian Corneci

Marian Corneci

blog feature toolkit

16 de junio de 2026

0 minutos de lectura

El 17 de junio de 2026, un atacante volvió a publicar todo el ámbito npm de @mastra, e introdujo una única dependencia maliciosa en 143 paquetes y contando, incluido @mastra/core, que tiene alrededor de 4 millones de descargas al mes y cientos de proyectos dependientes. La dependencia inyectada, easy-day-js, imita a dayjs. Su hook de instalación desactiva la verificación de TLS, descarga una carga útil de segunda etapa desde una dirección IP sin procesar y ejecuta en segundo plano un malware multiplataforma para robar criptomonedas. Este ataque a un paquete npm fue posible porque nunca se revocó el acceso al ámbito de una cuenta de un antiguo colaborador.

Acción necesaria: si instalaste algún paquete de @mastra, o cualquier paquete que dependa de uno, en un árbol nuevo o actualizado el 17 de junio de 2026 o después, considéralo un incidente de exposición de credenciales y billeteras, y sigue leyendo.

ACTUALIZACIÓN: Snyk agregó un nuevo paquete comprometido: @mastra/node-speaker, versión 0.1.1.

En resumen

  • Incidente: toma de control del ámbito npm de @mastra y republicación masiva con una dependencia maliciosa inyectada

  • Dependencia maliciosa: easy-day-js@1.11.22 (un impostor de dayjs que actúa como descargador de malware)

  • Aviso de Snyk: SNYK-JS-EASYDAYJS-17353313, código malicioso incrustado; afecta a easy-day-js 1.11.21 y 1.11.22

  • Paquetes afectados: prácticamente todo el ámbito @mastra, republicado el 17 de junio de 2026; la remediación de Mastra contempla 142 paquetes publicables

  • Versiones destacadas: @mastra/core@1.42.1, mastra@1.13.1, create-mastra@1.13.1

  • CVE / CVSS: no se asignó ninguno; se trata de un incidente activo de la cadena de suministro y el código fuente de Mastra no se modificó

  • Carga útil: malware multiplataforma para robar criptomonedas de billeteras y un troyano de acceso remoto con persistencia

  • Estado: se eliminó easy-day-js de npm, ehindero ya no es propietario del ámbito y Mastra publicó versiones limpias posteriores (PR #18056). La versión más reciente de @mastra/core latest volvió a ser la versión limpia 1.42.0. Considera cualquier versión comprometida que ya hayas resuelto como un incidente de exposición del host.

Cómo funcionó el ataque

El punto de entrada fueron credenciales antiguas de un mantenedor. El ámbito @mastra se publicó usando la cuenta npm ehindero, que pertenecía a un antiguo colaborador de Mastra. El historial de publicaciones del registro npm muestra versiones alfa legítimas de @mastra/core publicadas desde esta cuenta a finales de 2024 y principios de 2025, tras lo cual quedó inactiva. Nunca se revocó su acceso al ámbito.

La cuenta muestra indicios de haber sido tomada por un atacante, y no de una acción interna: entre ellos, un cambio del correo electrónico original del colaborador a ehindero2016@tutamail[.]com. Vale la pena detenerse en cómo funciona esto: npm no caduca los permisos para publicar en un ámbito cuando una cuenta está inactiva, por lo que una sola credencial antigua de mantenedor bastó para publicar en todos los paquetes del ámbito. La causa raíz fue la falta de higiene del proyecto, no una vulnerabilidad de día cero.

El vehículo: una línea en cada package.json

El atacante no tocó el código fuente de Mastra. El código malicioso se inyectó en los archivos tar publicados al momento de la publicación, y el PR de remediación de Mastra confirma que se verificó que el repositorio estuviera limpio de easy-day-js en todos los archivos package.json y de bloqueo (PR #18056). Cada versión maliciosa publicada en npm agregó exactamente una línea al archivo package.json publicado:

"easy-day-js": "^1.11.21"

La dependencia nunca se importa en el código fuente de Mastra. Su único propósito es incorporar un troyano durante la instalación. El truco está en el rango con acento circunflejo. El atacante publicó primero una versión limpia de easy-day-js@1.11.21 el 16 de junio: un impostor idéntico byte por byte a dayjs, hasta en el archivo incluido dayjs.min.js y la descripción del paquete. Al día siguiente, publicó easy-day-js@1.11.22 con el malware y la etiquetó como latest. Como 1.11.22 cumple con ^1.11.21, una ejecución normal de npm install resuelve directamente a la versión maliciosa.

Después, el 17 de junio de 2026, el atacante volvió a publicar el resto del ámbito de una sola vez, con la misma dependencia inyectada en cada paquete. La remediación de Mastra detalla con precisión el alcance del impacto: su changeset de emergencia publicó versiones posteriores limpias de 142 paquetes publicables del ámbito @mastra/*, además de mastra, create-mastra y mastracode (PR #18056). Los informes públicos situaron la cifra entre 80 y 144, según el momento de la consulta, pero conviene basarse en el dato del propio proveedor. La conclusión es la misma: se afectó prácticamente todo el ámbito.

En algunos paquetes, el atacante incluso publicó versiones superiores a la versión legítima latest (por ejemplo, @mastra/schema-compat@1.2.12, @mastra/react@1.0.1, @mastra/voice-playai@0.12.2). Esto obligó después a Mastra a fijar explícitamente versiones más altas, en vez de usar actualizaciones de parche normales para reemplazarlas (PR #18060).

El descargador del malware: desactivar TLS, descargar, desvincular y borrar

easy-day-js@1.11.22 incluye un archivo setup.cjs que se ejecuta como hook de postinstall. Durante la instalación:

  1. Desactiva la validación de certificados TLS asignando NODE_TLS_REJECT_UNAUTHORIZED='0', de modo que se complete una descarga HTTPS desde una IP sin procesar que usa un certificado autofirmado.

  2. Crea archivos indicadores (~/.pkg_history, ~/.pkg_logs) para llevar un registro de las instalaciones.

  3. Descarga una carga útil de segunda etapa desde https://23.254.164[.]92:8000/update/49890878 (alojada en Hostwinds).

  4. La guarda en el directorio temporal y la inicia como un proceso en segundo plano, oculto y desvinculado, sin mostrar nada en la consola.

  5. Se elimina para reducir los rastros forenses.

La carga útil: un malware multiplataforma para robar criptomonedas y un troyano de acceso remoto

La segunda etapa (SHA256 221c45a790dec2a296af57969e1165a16f8f49733aeab64c0bbd768d9943badf) es un malware ofuscado para robar criptomonedas de billeteras, del mismo tipo que Snyk ha rastreado en compromisos anteriores de npm. Revisa los perfiles de Chrome, Brave y Edge en busca de una lista codificada de extensiones de navegador para billeteras de criptomonedas, incluidas MetaMask, Phantom, Solflare, Coinbase Wallet, OKX y Keplr. Además de los datos de las billeteras, recopila el nombre de usuario, el nombre del host, el sistema operativo y la arquitectura, la versión de Node, las aplicaciones instaladas, el historial del navegador y la lista de procesos en ejecución. Luego codifica todo en base64 y lo envía en una señal JSON.

También establece persistencia haciéndose pasar por una herramienta de Node y envía señales a otro servidor de comando y control (C2) del troyano de acceso remoto (23.254.164[.]123/49890878) aproximadamente cada 10 minutos, mediante un certificado de prueba autofirmado de wolfSSL (CN=www.wolfssl.com, vencido en enero de 2018):

  • macOS: LaunchAgent en ~/Library/LaunchAgents/com.nvm.protocal.plist

  • Linux: servicio de usuario de systemd ~/.config/systemd/user/nvmconf.service

  • Windows: ejecución de PowerShell preparada en C:\ProgramData\NodePackages

La dependencia primero limpia y luego maliciosa, el descargador de malware setup en postinstall, la descarga a una IP sin procesar que elude TLS y la carga útil para robar criptomonedas se parecen mucho al compromiso de npm de Axios que Snyk analizó a principios de 2026, incluido el descargador de malware que se elimina después de ejecutarse durante la instalación. Microsoft Threat Intelligence atribuyó esa campaña anterior al actor que rastrea como Sapphire Sleet (BlueNoroff). La atribución de este incidente en particular no está confirmada y no especularemos al respecto; el patrón es relevante para quienes defienden sistemas, pero no debe presentarse como un hecho.

Análisis del impacto

Solo @mastra/core tiene alrededor de 4 millones de descargas al mes (registro npm) y cientos de proyectos dependientes; mastra suma aproximadamente 1.5 millones más (registro npm). Con 142 paquetes republicados en todo el ámbito, el volumen agregado de descargas mensuales alcanza decenas de millones, por lo que el alcance potencial del impacto es grande.

La exposición real es más acotada que lo que sugiere esa cifra general, y conviene ser precisos. Solo estás en riesgo si una compilación o máquina de desarrollo resolvió una de las versiones maliciosas durante el período de exposición. Los archivos de bloqueo son decisivos y constituyen el método seguro y reproducible para gestionar dependencias en proyectos npm:

  • Fijadas mediante un archivo de bloqueo confirmado en el repositorio a una versión anterior al incidente: una ejecución de npm ci no habría descargado la versión maliciosa. Probablemente no tengas problemas, pero verifícalo.

  • Sin archivo de bloqueo, con un rango flexible o con una instalación nueva o regeneración del archivo de bloqueo el 17 de junio o después: el rango con acento circunflejo habría resuelto a la versión maliciosa easy-day-js@1.11.22 y se habría ejecutado el hook de postinstall.

Como la carga útil se ejecuta durante la instalación, los ejecutores de CI, los agentes de compilación efímeros y las laptops de desarrolladores están dentro del alcance del incidente, no solo los servidores de producción. Cualquiera de esos hosts podría haber filtrado credenciales y datos de billeteras.

Detección: ¿estás expuesto?

1. Comprueba si easy-day-js alguna vez llegó a tu árbol de dependencias. Nunca debería aparecer legítimamente:

npm ls easy-day-js

grep -r "easy-day-js" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null

2. Audita las @mastra versiones que resolviste. Las versiones comprometidas se publicaron el 17 de junio de 2026 y no cuentan con procedencia de SLSA. Inspecciona lo que realmente fijó tu archivo de bloqueo:

npm ls @mastra/core mastra create-mastra

3. Analiza con Snyk. Snyk detecta el paquete malicioso como SNYK-JS-EASYDAYJS-17353313 (código malicioso incrustado):

snyk test

snyk monitor

4. Busca artefactos en cualquier máquina donde se haya ejecutado una instalación durante el período de exposición:

#Dropper markers

ls -la ~/.pkg_history ~/.pkg_logs 2>/dev/null

#Persistence

ls -la ~/Library/LaunchAgents/com.nvm.protocal.plist 2>/dev/null      # macOS

ls -la ~/.config/systemd/user/nvmconf.service 2>/dev/null             # Linux

dir "C:\ProgramData\NodePackages"                                      # Windows

5. Revisa los registros de tráfico saliente para detectar conexiones a 23.254.164[.]92:8000 o 23.254.164[.]123, o a cualquier dirección de 23.254.164.0/24.

Si quieres una guía práctica para detectar y corregir con Snyk un compromiso de todo un ámbito npm de este tipo, esta demostración de remediación explica el proceso de principio a fin:

Shai-Hulud NPM Attack: Remediation with Snyk

Ataque Shai-Hulud a NPM: remediación con Snyk (un proceso práctico de remediación para un ataque a la cadena de suministro de npm mediante una republicación masiva).

Remediación

Si easy-day-js no aparece y tu archivo de bloqueo fijó @mastra a versiones anteriores al incidente: confírmalo con los pasos de detección anteriores, mantén las versiones fijadas en el archivo de bloqueo y continúa.

Si resolviste una versión maliciosa, considera comprometido cualquier host afectado.

  1. Actualiza a una versión limpia; no te limites a fijar una versión anterior. Mastra respondió publicando versiones limpias posteriores para los 142 paquetes publicables y moviendo la etiqueta de distribución latest más allá de las versiones comprometidas (PR #18056, PR #18049), en lugar de depender de la retirada de paquetes. Actualiza a la versión limpia actual (por ejemplo, @mastra/core@1.42.0 o una posterior), regenera un archivo de bloqueo limpio y elimina cualquier rastro de easy-day-js. Como el atacante publicó algunas versiones superiores a la latest legítima, verifica que la versión que elijas sea una versión de Mastra confirmada como segura y no una versión maliciosa aislada.

  2. Rota todas las credenciales a las que pudo acceder el host: claves de la nube, secretos y tokens de CI, claves de API de LLM y otros servicios, tokens de npm y claves SSH. Mastra es un framework de agentes, así que es especialmente probable que haya claves de proveedores de LLM.

  3. Migra las billeteras de criptomonedas: si el perfil de navegador de la máquina tenía una extensión de billetera objetivo, asume que la frase semilla y las claves quedaron expuestas y transfiere los fondos a una billetera nueva desde un dispositivo limpio.

  4. Elimina la persistencia: borra el LaunchAgent, la unidad de systemd o los archivos preparados en C:\ProgramData\NodePackages, termina el proceso desvinculado y elimina los indicadores del dropper.

  5. Reinstala la imagen del sistema cuando sea viable. Si un troyano de acceso remoto logró establecer persistencia, la opción más segura es reconstruir el sistema desde cero.

Para reducir la exposición a este tipo de ataque en el futuro:

  • Desactiva los scripts de instalación de forma predeterminada con npm config set ignore-scripts true, y permítelos solo cuando una compilación realmente los necesite. Esto neutraliza los droppers de postinstall y es una de las prácticas recomendadas de seguridad para npm de Snyk.

  • Confirma los archivos de bloqueo y usa npm ci en CI para que las compilaciones sean reproducibles y un cambio en la etiqueta latest no vuelva a resolver dependencias de forma silenciosa.

  • Exige procedencia. Mastra generaba procedencia SLSA en las publicaciones de CI, pero no era obligatoria, por lo que un token simple aún podía publicar sin atestaciones. Esta misma brecha permitió que se distribuyeran versiones maliciosas en el compromiso del paquete Nx; exigir procedencia al consumir paquetes eleva el nivel de protección.

  • Busca dependencias fantasma. Que un paquete maduro y de uso generalizado incorpore de pronto una sola dependencia sin usar es exactamente la señal que vemos aquí. La priorización basada en riesgos y el descubrimiento de activos en todo tu entorno te ayudan a identificar dónde terminó un paquete afectado y qué instancias son accesibles y contienen credenciales, para que primero corrijas los hosts expuestos en lugar de revisar de una vez cada instalación de todo el ámbito.

Contenido relacionado de Snyk

Este es el caso más reciente de una serie de ataques de toma de control de ámbitos npm y cuentas de mantenedores en 2026. El patrón —una cuenta de mantenedor comprometida que impulsa una republicación automatizada y rápida— es el mismo que está detrás de las campañas Mini Shai-Hulud: 

Mini Shai-Hulud: The Most Sophisticated NPM Supply Chain Attack of 2026

Mini Shai-Hulud: el ataque a la cadena de suministro de NPM más sofisticado de 2026 (un recorrido por cómo se usa una sola cuenta de mantenedor comprometida para introducir troyanos en cientos de paquetes npm a la vez, y cómo detectar y remediar la exposición).

Para conocer más sobre esta misma familia de ataques y las medidas de defensa, consulta la cobertura de Snyk sobre el compromiso del paquete npm Axios, el ataque Mini Shai-Hulud a AntV y a TanStack, el gusano de propagación automática node-gyp y los compromisos de tinycolor y ngx-bootstrap. Para aprender a reforzar tu canalización de instalación, consulta Seguridad en NPM: cómo prevenir ataques a la cadena de suministro y la lección de Snyk Learn sobre el compromiso de un paquete legítimo.

Cronología

  • Desde fines de 2024 hasta principios de 2025: la cuenta ehindero publica versiones alfa legítimas de @mastra/core y luego queda inactiva. Nunca se revoca el acceso al ámbito.

  • 16 de junio de 2026: se publica una versión limpia de easy-day-js@1.11.21 como señuelo, haciéndose pasar por dayjs.

  • 17 de junio de 2026, ~01:01 UTC: se publica la versión maliciosa easy-day-js@1.11.22 y se etiqueta como latest.

  • 17 de junio de 2026, ~01:12 a 02:36 UTC: se republica la mayor parte del ámbito @mastra/* con la dependencia easy-day-js inyectada.

  • 17 de junio de 2026: varios proveedores de seguridad divulgan públicamente el incidente; easy-day-js se elimina de npm y las versiones maliciosas se marcan como tales (aviso de Snyk SNYK-JS-EASYDAYJS-17353313).

  • 17 de junio de 2026 (ese mismo día): Mastra responde eliminando al propietario no autorizado, abriendo cambiosets de emergencia para publicar versiones limpias (PR #18049), publicando versiones posteriores de los 142 paquetes publicables (PR #18056) y fijando versiones explícitas superiores allí donde el atacante había publicado una versión posterior a latest (PR #18060).

Protege tu cadena de suministro con Snyk

Los problemas de seguridad de la cadena de suministro afectaron al 87 % de las personas encuestadas. Protege la tuya con Snyk.