Skip to content

Back to the catalog

Over 140 popular Mastra npm Packages Hit by Supply Chain Attack
aikido.devwriteup

Over 140 popular Mastra npm Packages Hit by Supply Chain Attack

Aikido details a supply chain attack in which an attacker took over the entire @mastra npm scope, republishing 141 packages (including @mastra/core with 918K weekly downloads) to add a malicious dependency, easy-day-js, a dayjs clone. A staged clean-then-malicious version (1.11.21 → 1.11.22) exploited npm's caret resolution so the postinstall script setup.cjs fetched a second-stage payload from a C2 server, spawned it as a detached background process targeting 160+ browser crypto wallet extensions, and self-deleted to erase forensic evidence. Aikido notes the attack closely mirrors the earlier axios compromise (same Hostwinds infrastructure pattern, decoy-then-malicious staging, postinstall hook, self-deletion).

TL;DR Attacker hijacked the entire @mastra npm scope to inject a malicious dayjs-clone dependency (easy-day-js) whose postinstall hook drops a crypto-wallet-stealing RAT via a self-deleting dropper, mirroring the axios supply chain attack.
Document

What it is

A supply-chain attack on the entire @mastra npm scope (a popular open-source AI agent framework), detected by Aikido on June 17th. An attacker republished 141 packages in a burst between 01:15–02:00 UTC, injecting a single malicious dependency into each. Named packages include @mastra/core (918K weekly downloads, republished as 1.42.1), mastra@1.13.1, and create-mastra@1.13.1.

How it works

The injected dependency is easy-day-js, a malicious clone of dayjs published from a separate attacker account a day earlier. The trick is version resolution: the compromised packages depend on ^1.11.21, and 1.11.21 was a clean copy of dayjs with no install hooks — so auditing the pinned version reveals nothing. The malicious 1.11.22 was published the next day, and npm's caret resolution silently pulls it in as latest.

1.11.22 adds a postinstall hook running an obfuscated setup.cjs. It:

  1. Fetches a second-stage payload from 23[.]254[.]164[.]92:8000
  2. Writes it to a randomly named .js file in the OS temp dir
  3. Spawns it fully detached (stdio: ignore, windowsHide: true), passing 23[.]254[.]164[.]123:443 as an argument
  4. Self-deletes to remove forensic traces

The second stage is a long-lived RAT that collects system info and targets 160+ browser crypto-wallet extensions (MetaMask, Keplr, Coinbase), establishes persistence disguised as node tooling on macOS/Windows/Linux, and phones home to 23[.]254[.]164[.]123:443.

flowchart TD
    A["package depends on easy-day-js ^1.11.21"] --> B{npm caret resolution}
    B -->|"pins 1.11.21 (clean decoy)"| C["audit finds nothing"]
    B -->|"latest = 1.11.22"| D["postinstall runs setup.cjs"]
    D --> E["fetch payload from :8000"]
    E --> F["spawn detached RAT, self-delete"]
    F --> G["target 160+ wallets, persist, C2 :443"]

Preconditions / Affected

Any project installing an affected @mastra package (or easy-day-js) after the malicious 1.11.22 publish, where the postinstall hook is allowed to run. Because caret ranges resolve to latest, installs and CI builds that don't pin exact versions are exposed.

What to do

  • Aikido users: check the central feed, filter on malware issues (surfaces as a 100/100 critical), and trigger a manual rescan — nightly rescan may not have run yet.
  • Audit lockfiles and installed trees for easy-day-js@1.11.22 and the affected @mastra versions.
  • Block/monitor the network IOCs: 23[.]254[.]164[.]92:8000 (first-stage payload download) and 23[.]254[.]164[.]123:443 (second-stage RAT callback).
  • The page suggests Aikido Safe Chain (open source), which intercepts npm, npx, yarn, pnpm, and pnpx to check packages before install.

Caveats

The report attributes the compromise to "likely" a maintainer account or CI token takeover — the exact initial vector isn't confirmed. The affected-package list in the fetched text is truncated mid-scope (@mastra/i…), so treat the full 141-package set as larger than what's shown here.

Organisations named here

  • easy-day-js
  • Hostwinds

Technologies named here

  • @mastra/core
  • Aikido
  • Aikido Device Protection
  • mastra
  • Aikido Safe Chain
  • create-mastra
  • Aikido Intel
  • easy-day-js
  • @mastra/acp
  • @mastra/agent-browser
  • @mastra/agent-builder
  • @mastra/agentcore
  • @mastra/agentfs
  • @mastra/ai-sdk
  • @mastra/arize
  • @mastra/arthur
  • @mastra/astra
  • @mastra/auth
  • @mastra/auth-auth0
  • @mastra/auth-better-auth
  • @mastra/auth-clerk
  • @mastra/auth-cloud
  • @mastra/auth-firebase
  • @mastra/auth-okta
  • @mastra/auth-studio
  • @mastra/auth-supabase
  • @mastra/auth-workos
  • @mastra/azure
  • @mastra/blaxel
  • @mastra/braintrust
  • @mastra/brightdata
  • @mastra/browser-firecrawl
  • @mastra/browser-viewer
  • @mastra/chroma
  • @mastra/claude
  • @mastra/clickhouse
  • @mastra/client-js
  • @mastra/cloud
  • @mastra/cloudflare
  • @mastra/cloudflare-d1
  • @mastra/codemod
  • @mastra/convex
  • @mastra/couchbase
  • @mastra/cursor
  • @mastra/dane
  • @mastra/datadog
  • @mastra/daytona
  • @mastra/deployer
  • @mastra/deployer-cloud
  • @mastra/deployer-cloudflare
  • @mastra/deployer-netlify
  • @mastra/deployer-vercel
  • @mastra/docker
  • @mastra/dsql
  • @mastra/duckdb
  • @mastra/dynamodb
  • @mastra/e2b
  • @mastra/editor
  • @mastra/elasticsearch
  • @mastra/engine
  • @mastra/evals
  • @mastra/express
  • @mastra/fastembed
  • @mastra/fastify
  • @mastra/files-sdk
  • @mastra/gcs
  • @mastra/github-signals
  • @mastra/google-cloud-pubsub
  • @mastra/google-drive
  • @mastra/hono
  • @mastra/inngest
  • @mastra/koa
  • @mastra/laminar
  • @mastra/lance
  • @mastra/langfuse
  • @mastra/langsmith
  • @mastra/libsql
  • @mastra/loggers
  • @mastra/longmemeval
  • @mastra/mcp
  • @mastra/mcp-docs-server
  • @mastra/mcp-registry-registry
  • @mastra/mem0
  • @mastra/memory
  • @mastra/modal
  • @mastra/mongodb
  • @mastra/mssql
  • @mastra/mysql
  • @mastra/nestjs
  • @mastra/node-audio
  • @mastra/node-speaker
  • @mastra/observability
  • @mastra/openai
  • @mastra/opencode
  • @mastra/opensearch
  • @mastra/otel-bridge
  • @mastra/otel-exporter
  • @mastra/perplexity
  • @mastra/pg
  • @mastra/pinecone
  • @mastra/playground-ui
  • @mastra/posthog
  • @mastra/qdrant
  • @mastra/rag
  • @mastra/railway
  • @mastra/react
  • @mastra/redis
  • @mastra/redis-streams
  • @mastra/s3
  • @mastra/s3vectors
  • @mastra/schema-compat
  • @mastra/sentry
  • @mastra/server
  • @mastra/slack
  • @mastra/spanner
  • @mastra/speech-azure
  • @mastra/speech-elevenlabs
  • @mastra/speech-google
  • @mastra/speech-ibm
  • @mastra/speech-murf
  • @mastra/speech-openai
  • @mastra/speech-replicate
  • @mastra/speech-speechify
  • @mastra/stagehand
  • @mastra/tavily
  • @mastra/temporal
  • @mastra/turbopuffer
  • @mastra/twilio
  • @mastra/upstash
  • @mastra/vectorize
  • @mastra/vercel
  • @mastra/voice-aws-nova-sonic
  • @mastra/voice-azure
  • @mastra/voice-cloudflare
  • @mastra/voice-deepgram
  • @mastra/voice-elevenlabs
  • @mastra/voice-gladia
  • @mastra/voice-google
  • @mastra/voice-google-gemini-live
  • @mastra/voice-inworld
  • @mastra/voice-modelslab
  • @mastra/voice-murf
  • @mastra/voice-openai
  • @mastra/voice-openai-realtime
  • @mastra/voice-playai
  • @mastra/voice-sarvam
  • @mastra/voice-speechify
  • @mastra/voice-xai-realtime
  • Browser-based crypto wallet extensions
  • npm
  • Aikido Security
  • axios

Techniques named here

  • npm scope takeover / supply chain attack
  • Malicious dependency injection via clone package
  • Clean decoy version followed by malicious update
  • Dependency version pinning bypass via caret resolution
  • Malicious postinstall script
  • C2 payload retrieval
  • Detached background process execution
  • Self-deletion / anti-forensics
  • Persistence via disguised process naming
  • Crypto wallet targeting

Threat actors named here

  • Unnamed attacker
  • axios compromise attacker