Editorial

@mastra npm supply chain attack: 90+ packages, no CVEs

RobertUpdated Jun 23, 20269 min read
JSON API response showing supply_chain.compromised true for a Mastra npm package, with a circuit network visualization indicating a compromised node in the supply chain.

The Mastra AI supply chain attack: 145 npm packages, no CVEs, and the signal that caught it#

June 22, 2026

On June 17, 145 npm packages across the @mastra scope were compromised in a coordinated supply chain attack now attributed to Sapphire Sleet, a North Korean state-sponsored group. The entire Mastra AI agent framework ecosystem was hit simultaneously. @mastra/core alone receives over 918,000 weekly downloads.

No CVEs were assigned. No vulnerability scanners flagged anything. Every compromised package passed a standard CVE check clean.

This is what that looks like in the Attestd API.


What happened#

Mastra is a TypeScript framework for building AI agents. The @mastra npm scope covers the core framework, integrations, deployers, memory backends, voice providers, and observability tooling. Developers building autonomous systems use it to wire together LLMs, tools, and persistent workflows.

The attack began with a compromised maintainer. The ehindero npm account belonged to a current, active Mastra employee whose machine was compromised via a social engineering attack originating on LinkedIn. The attacker made contact posing as a professional connection, directed the employee to a suspicious link during a call, and gained access. The compromised account held publishing rights across the @mastra package scope, with MFA in place but token bypass not yet removed.

The attackers did not inject malicious code directly into the @mastra packages. Instead they added a single malicious dependency named easy-day-js to each package's dependency list. This is a significant technical distinction: the packages themselves appeared clean. The malicious behaviour was introduced at install time through a transitive dependency.

easy-day-js was first published on June 16, 2026 at 7:05 AM UTC as a functionally clean clone of the widely-used dayjs date library. The malicious payload was introduced in a second publish on June 17, 2026 at 1:01 AM UTC. The clean version was a deliberate decoy, published first to establish a history and reduce suspicion.

Once armed, easy-day-js executed a postinstall hook that deployed a malware dropper. The dropper disabled TLS certificate verification, contacted attacker-controlled command-and-control infrastructure, downloaded a second-stage payload, and executed it as a detached background process before erasing itself to reduce forensic traces.

The second-stage payload was a cross-platform information stealer targeting Windows, Linux, and macOS. It collected browser histories, running processes, and installed applications. It checked for 166 cryptocurrency wallet browser extensions. It established persistence using platform-appropriate mechanisms: Windows Registry Run keys on Windows, LaunchAgents on macOS, and systemd services on Linux. It then polled the C2 server for additional commands, including downloading and executing further modules.

"Because Mastra sits at the intersection of AI development and cloud infrastructure, its packages are routinely installed in environments that hold some of the most sensitive credentials in modern software development," StepSecurity noted in its analysis. "This makes the Mastra ecosystem an exceptionally high-value target for supply chain attackers."

Mastra has confirmed the incident and removed the affected package versions. The root cause, in their words, was a compromised maintainer. MFA was required but token bypass was not blocked, which allowed a personal token to publish without triggering the MFA requirement.

This was not an opportunistic attack. Mastra is an AI agent framework. The targets were developers building autonomous systems.


What the API returns#

The compromised version of @mastra/core is 1.42.1. Here is what Attestd returns for that version today.

bash
curl "https://api.attestd.io/v1/check?product=%40mastra%2Fcore&version=1.42.1" \
  -H "Authorization: Bearer $ATTESTD_API_KEY"
json
{
  "product": "@mastra/core",
  "version": "1.42.1",
  "supported": true,
  "risk_state": "none",
  "risk_factors": [],
  "actively_exploited": false,
  "remote_exploitable": false,
  "authentication_required": false,
  "patch_available": false,
  "fixed_version": null,
  "confidence": 0.95,
  "cve_ids": [],
  "cves": null,
  "last_updated": "2026-06-22T20:58:27.722520Z",
  "supply_chain": {
    "compromised": true,
    "sources": ["osv"],
    "malware_type": "malware",
    "description": "Malicious code in @mastra/core (npm)",
    "advisory_url": null,
    "compromised_at": "2026-06-17T04:55:41Z",
    "removed_at": null
  },
  "typosquat": null
}

risk_state: none. No CVE IDs. No risk factors. Every CVE-based gate in every CI/CD pipeline that evaluated @mastra/core at 1.42.1 saw a clean result.

supply_chain.compromised: true. That is the field that carries the signal. The attack class is malicious transitive dependency injection via hijacked maintainer account. It does not produce CVEs. It does not appear in NVD or CISA KEV. The only way to detect it programmatically is through supply chain integrity signals from sources like OSV.dev that track known-compromised package versions.

This is the signal pattern that defines this attack class: risk_state: none with supply_chain.compromised: true. A security layer that evaluates only CVE data passes this attack entirely.


The provenance gap#

Mastra's legitimate releases are published from CI and carry SLSA provenance attestations. The attacker published from a personal token, which dropped the provenance entirely.

Any install tool configured to verify signatures or require attestations would have rejected every package in this wave. npm's own audit signatures feature and policies that require SLSA attestations are both capable of catching this. Neither is on by default.

This is a structural property of the attack that extends beyond Mastra. A maintainer account with scope publishing rights and no attestation requirement is a viable attack surface in any large npm package ecosystem. The Mastra incident is not an isolated event.


A pattern: the Axios precedent#

In April 2026, the Axios HTTP client was compromised in a structurally identical attack. A legitimate maintainer account was hijacked, publish rights were abused, and the attackers inserted a malicious transitive dependency that executed at install time. That dependency impersonated crypto-js. In the Mastra attack, it impersonated dayjs. In both cases, a clean decoy version was published first and the malicious payload introduced in a subsequent publish.

Microsoft attributed both the Axios compromise and the Mastra attack to Sapphire Sleet. The infrastructure and post-compromise tactics are consistent across both campaigns. The same group is executing the same playbook, iterating on target selection.

The pattern is: compromise a maintainer on a high-value developer tooling package, inject a malicious transitive dependency impersonating a staple library, execute at install time, steal credentials and cryptocurrency. AI developer tooling is the current target category.


The typosquat signal came first#

Attestd's pipeline flagged mastraqqq on June 16, the day before the @mastra scope compromise was disclosed.

mastraqqq is a typosquat of the root mastra package. It is a separate package and a separate signal from the easy-day-js dependency used in the main attack. The pipeline flagged it as malware and committed it to the detection ledger on June 16, the same day easy-day-js was being published in its clean decoy form.

Whether mastraqqq was a probe, an early test of the attack infrastructure, or a parallel operation is not something Attestd can determine from the available data. What the ledger shows is that anomalous activity in the Mastra package namespace was flagged before the main event was disclosed. Two independent signals in the same namespace on the same day.


Why this attack targets AI infrastructure specifically#

Mastra is not a generic npm package. It is a framework for building AI agents. Developers using it are constructing autonomous systems that make decisions, execute code, manage infrastructure, and interact with external services.

Compromising the development environment of someone building an autonomous agent is a different threat model than compromising a web application. The malware targets credentials, API keys, and authentication tokens. In an AI agent development context, those credentials may include cloud provider access, LLM API keys, database connections, and service account tokens that the agent itself uses at runtime.

Sapphire Sleet's known focus on cryptocurrency theft is consistent with targeting AI developer tooling. The developers most likely to be building with Mastra in mid-2026 are also the developers most likely to hold high-value API access and cryptocurrency wallet credentials.

This is not the last time AI agent frameworks will be targeted at this layer.


What this means for autonomous systems consuming dependencies#

An autonomous system that installs or updates its own dependencies needs supply chain signals, not just CVE signals. The attack surface is different. The detection mechanism is different. And the consequences of a compromised dependency in an autonomous pipeline are different from a compromised dependency in a human-reviewed codebase, because there may be no human in the loop to notice unexpected behaviour.

"Even if the first-stage package is removed after installation, the second-stage process may continue running and may have already installed persistence," JFrog noted in its analysis. Any workstation, CI runner, or build environment that installed the affected versions should be treated as potentially compromised, with credentials rotated and hosts audited.

The Attestd detection ledger records every supply chain detection with a timestamp and a GPG-signed commit. The @mastra entries are timestamped June 17, the date of first public disclosure. The mastraqqq entry is timestamped June 16. Both are independently verifiable against the OSV advisory timestamps.

The ledger is public at github.com/attestd-io/detection-ledger and the live dashboard is at attestd.io/docs/detection-ledger.


Coverage#

Attestd covers all 145 packages in this incident. Every package returns supply_chain.compromised: true sourced from OSV. No additional configuration is required.

API documentation is at attestd.io/docs.


Full list of covered packages (145 of 145)#

All return supported: true and supply_chain.compromised: true sourced from OSV.

Core

create-mastra easy-day-js mastra @mastra/core @mastra/server @mastra/client-js @mastra/editor @mastra/engine @mastra/playground-ui @mastra/schema-compat

Agents

@mastra/agent-browser @mastra/agent-builder @mastra/agentcore @mastra/agentfs @mastra/acp

Auth

@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

Deployers

@mastra/deployer @mastra/deployer-cloud @mastra/deployer-cloudflare @mastra/deployer-netlify @mastra/deployer-vercel

Databases, storage and vector

@mastra/astra @mastra/chroma @mastra/clickhouse @mastra/cloudflare-d1 @mastra/convex @mastra/couchbase @mastra/dsql @mastra/duckdb @mastra/dynamodb @mastra/elasticsearch @mastra/gcs @mastra/lance @mastra/libsql @mastra/mongodb @mastra/mssql @mastra/mysql @mastra/opensearch @mastra/pg @mastra/pinecone @mastra/qdrant @mastra/redis @mastra/redis-streams @mastra/s3 @mastra/s3vectors @mastra/spanner @mastra/turbopuffer @mastra/upstash @mastra/vectorize

AI and ML integrations

@mastra/ai-sdk @mastra/arize @mastra/arthur @mastra/braintrust @mastra/claude @mastra/evals @mastra/fastembed @mastra/laminar @mastra/langfuse @mastra/langsmith @mastra/longmemeval @mastra/mem0 @mastra/memory @mastra/openai @mastra/perplexity @mastra/posthog @mastra/rag

Observability

@mastra/datadog @mastra/loggers @mastra/observability @mastra/otel-bridge @mastra/otel-exporter @mastra/sentry

Web framework adapters

@mastra/express @mastra/fastify @mastra/hono @mastra/koa @mastra/nestjs @mastra/react @mastra/slack @mastra/twilio

MCP

@mastra/mcp @mastra/mcp-docs-server @mastra/mcp-registry-registry

Voice

@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/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

Infrastructure and tooling

@mastra/azure @mastra/blaxel @mastra/brightdata @mastra/browser-firecrawl @mastra/browser-viewer @mastra/cloud @mastra/cloudflare @mastra/codemod @mastra/cursor @mastra/dane @mastra/daytona @mastra/docker @mastra/e2b @mastra/files-sdk @mastra/github-signals @mastra/google-cloud-pubsub @mastra/google-drive @mastra/inngest @mastra/modal @mastra/node-audio @mastra/node-speaker @mastra/opencode @mastra/railway @mastra/stagehand @mastra/tavily @mastra/temporal @mastra/vercel

Typosquat detected June 16 (day before disclosure)

mastraqqq (1.13.1)