Toma del scope npm de Mastra: una cuenta de mantenedor inactiva envenena un framework de agentes de IA
El 17 de junio de 2026, una cuenta de colaborador olvidada republicó todo el scope npm @mastra — unos 142 paquetes — con una dependencia maliciosa que instala un ladrón de criptomonedas y un RAT. Una credencial caducada, no un zero-day.
¿Qué es esto?
El 17 de junio de 2026, un atacante republicó la totalidad del scope npm @mastra — el espacio de nombres de Mastra, un popular framework TypeScript de código abierto para construir agentes de IA — inyectando una única dependencia maliciosa en cada paquete. La biblioteca inyectada, easy-day-js, es un clon de dayjs cuyo hook de instalación descarga y ejecuta un ladrón de criptomonedas multiplataforma y un troyano de acceso remoto (RAT). El compromiso fue divulgado el mismo día por varios proveedores, entre ellos Snyk, SafeDep, Endor Labs, además de JFrog, Socket y StepSecurity (vía The Hacker News).
No se asignó ningún CVE y el código fuente de Mastra nunca se modificó. No fue un error de código. El punto de entrada fue una credencial de mantenedor inactiva: el scope @mastra se publicaba con la cuenta npm ehindero, la de un verdadero excolaborador de Mastra cuyo acceso de publicación nunca se revocó. npm no caduca los permisos de scope por inactividad, así que una sola credencial caducada bastó para publicar en cada paquete del espacio de nombres. Como resume Snyk, la causa raíz es de higiene del proyecto, no un zero-day.
Cómo funciona
El ataque se ocultaba en el árbol de dependencias, no en el código. El atacante publicó primero, el 16 de junio de 2026, una versión limpia y plenamente funcional de easy-day-js@1.11.21 — una imitación de dayjs byte a byte, hasta el dayjs.min.js incluido y la descripción del paquete — para servir de tapadera. Al día siguiente, hacia las 01:01 UTC del 17 de junio, publicó easy-day-js@1.11.22 con el malware, etiquetándola como latest. Cada versión @mastra envenenada añadía exactamente una línea a su package.json publicado:
"easy-day-js": "^1.11.21"
El rango con caret es el truco: 1.11.22 satisface ^1.11.21, de modo que un npm install normal resuelve directamente a la versión armada. El código de Mastra nunca importa la dependencia; existe solo para arrastrar el troyano en la instalación. Entre las 01:12 y las 02:36 UTC aproximadamente — una ráfaga automatizada de unos 88 minutos — se republicó el resto del scope. La remediación de Mastra enumera con precisión el radio de impacto: 142 paquetes publicables en @mastra/*, más mastra, create-mastra y mastracode; los recuentos públicos iban de 80 a 144 según la instantánea.
El malware se ejecuta desde un hook postinstall. En la instalación, desactiva la validación de certificados TLS (NODE_TLS_REJECT_UNAUTHORIZED='0'), descarga una carga de segunda etapa desde una IP en crudo mediante un certificado autofirmado (23.254.164[.]92:8000), la escribe en un directorio temporal, la lanza como proceso en segundo plano separado y oculto, y luego se autoelimina para reducir las trazas forenses. La segunda etapa es un ladrón de información ofuscado que lee los perfiles de Chrome, Brave y Edge en busca de una lista codificada de más de 160 extensiones de monederos de criptomonedas (MetaMask, Phantom, Solflare, Coinbase Wallet, OKX, Keplr), recopila metadatos del host e historial de navegación, y emite señales a un C2 RAT independiente (23.254.164[.]123) aproximadamente cada 10 minutos. Instala persistencia disfrazada de herramientas Node en las tres plataformas: un LaunchAgent en macOS, un servicio de usuario systemd en Linux y una ruta de staging C:\ProgramData\NodePackages en Windows.
Por qué importa
Como la carga se ejecuta en el momento de la instalación, la exposición no se limita a producción. Runners de CI, agentes de compilación efímeros y portátiles de desarrolladores entran todos en el alcance en cuanto resuelven una versión envenenada. @mastra/core acumula unos 4 millones de descargas al mes y tiene cientos de proyectos dependientes, así que el alcance agregado se cuenta en decenas de millones de instalaciones.
Mastra se sitúa justo donde quieren estar los atacantes de cadena de suministro: en la intersección del desarrollo de IA y la infraestructura cloud. Como señala StepSecurity, sus paquetes se instalan habitualmente en entornos que albergan algunas de las credenciales más sensibles del software moderno — y para un framework de agentes eso significa claves de API de proveedores de LLM junto con claves cloud, secretos de CI y claves SSH. Un ladrón de monederos y credenciales que aterriza en ese contexto es un objetivo casi ideal. Cabe destacar que Mastra generaba atestaciones de procedencia SLSA en sus publicaciones de CI pero no las exigía; un simple token personal podía, por tanto, publicar sin atestación — y lo hizo.
Defensas
Desactive los scripts de instalación por defecto. Establecer npm config set ignore-scripts true neutraliza droppers de postinstall como este; solo vuelva a habilitar scripts para los pocos paquetes que realmente los necesiten.
Versione los lockfiles y compile con npm ci. Un lockfile fijado a una versión anterior al incidente garantiza que un npm ci nunca habría resuelto la versión armada easy-day-js@1.11.22. Un rango demasiado amplio, un lockfile ausente o cualquier instalación nueva a partir del 17 de junio es exactamente lo que permite que el rango con caret se vuelva a resolver en silencio.
Exija la procedencia, no se limite a generarla. Una instalación que verifica firmas — npm audit signatures, o una política que rechace paquetes sin atestación — habría rechazado cada paquete de esta oleada, porque el atacante descartó la procedencia que normalmente produce el pipeline de CI legítimo.
Vigile las dependencias fantasma. Un paquete maduro y ampliamente usado que de repente gana una única dependencia no utilizada es exactamente la señal aquí. Trátelo como una bandera roja en revisión y en política automatizada.
Revoque los accesos de mantenedores caducados. Audite quién puede publicar en sus scopes, retire las cuentas inactivas y aplique 2FA y flujos de publicación de confianza. Todo el incidente se sostuvo sobre una credencial que nadie había retirado.
Si resolvió una versión envenenada, trate el host como comprometido: actualice a una versión limpia conocida (por ejemplo @mastra/core@1.42.0 o superior — no se limite a fijar hacia abajo, ya que el atacante publicó algunas versiones por encima del latest legítimo), rote todas las credenciales que la máquina pudiera alcanzar (cloud, CI, npm, SSH y, sobre todo, claves de API de LLM), mueva los monederos cripto a un dispositivo limpio, elimine los artefactos de persistencia y reinstale el sistema cuando sea posible.
Estado
| Elemento | Detalle |
|---|---|
| Incidente | Toma del scope npm @mastra, republicación masiva con dependencia inyectada |
| Fecha | 17 de junio de 2026 (señuelo easy-day-js@1.11.21 publicado el 16 de junio) |
| Paquete malicioso | easy-day-js@1.11.22 (dropper); marcador easy-day-js@1.11.21 (señuelo limpio) |
| Causa raíz | Cuenta npm de excolaborador inactiva (ehindero), acceso de publicación nunca revocado |
| Radio de impacto | ~142 paquetes publicables @mastra/*; recuentos públicos 80–144 |
| Carga útil | Ladrón de monederos cripto + RAT con persistencia, multiplataforma |
| CVE / CVSS | Ninguno asignado; código fuente sin modificar, malicia introducida al publicar |
| Estado | Versiones maliciosas retiradas; versiones limpias publicadas por adelantado el mismo día (p. ej. @mastra/core@1.42.0) |
Sources
- → https://snyk.io/blog/a-forgotten-contributor-account-compromised-the-entire-mastra-npm-package-scope/
- → https://thehackernews.com/2026/06/144-mastra-npm-packages-compromised-via.html
- → https://safedep.io/mastra-npm-scope-takeover-supply-chain-attack/
- → https://www.endorlabs.com/learn/mastra-npm-org-compromised-multiple-packages-trojanized-to-drop-a-remote-payload-via-easy-day-js