Skip to content

Back to the catalog

A Forgotten Contributor Account Compromised the Entire Mastra npm Package Scope
snyk.iowriteup

A Forgotten Contributor Account Compromised the Entire Mastra npm Package Scope

Snyk details how a dormant, never-revoked npm contributor account (ehindero) was used to republish the entire @mastra scope (142+ packages, ~4M monthly downloads for @mastra/core alone) with an injected dependency, easy-day-js, a byte-for-byte dayjs impersonator. The postinstall hook in easy-day-js@1.11.22 disables TLS verification, pulls a second-stage payload from a raw IP, and drops a cross-platform cryptocurrency wallet stealer plus a RAT with OS-specific persistence (LaunchAgent, systemd unit, PowerShell staging) that beacons every 10 minutes over a self-signed wolfSSL certificate. The piece covers detection steps, the Snyk advisory (SNYK-JS-EASYDAYJS-17353313), and draws parallels to the earlier Axios npm compromise attributed by Microsoft to Sapphire Sleet (BlueNoroff).

TL;DR A stale, never-revoked maintainer account was used to republish the entire @mastra npm scope with a dayjs-impersonating dependency that drops a crypto-stealing RAT via a postinstall hook.
Document

What it is

An active npm supply-chain incident: a takeover of the entire @mastra scope, executed via a stale contributor account (ehindero) whose publish access was never revoked. The attacker mass-republished the scope on June 17, 2026, injecting a single malicious dependency, easy-day-js@1.11.22 (Snyk advisory SNYK-JS-EASYDAYJS-17353313). No CVE assigned; the Mastra source repo itself was never modified — the poison lived only in published tarballs.

How it works

The attacker staged the dependency to defeat caret ranges. On June 16 they published a clean easy-day-js@1.11.21 (a byte-for-byte dayjs impersonator); the next day they published 1.11.22 carrying the malware and tagged it latest. Because 1.11.22 satisfies ^1.11.21, a normal install resolves to the armed version. Each republished package gained exactly one injected package.json line pulling in easy-day-js; it is never imported in source — it exists only to run a postinstall.

setup.cjs (postinstall) sets NODE_TLS_REJECT_UNAUTHORIZED='0', writes marker files ~/.pkg_history and ~/.pkg_logs, downloads a second stage from https://23.254.164[.]92:8000/update/49890878, spawns it detached/hidden, then deletes itself. The payload (SHA256 221c45a790dec2a296af57969e1165a16f8f49733aeab64c0bbd768d9943badf) reads Chrome/Brave/Edge profiles for wallet extensions, exfiltrates host + browser data as a base64 JSON beacon, and beacons a RAT C2 at 23.254.164[.]123/49890878 roughly every 10 minutes.

Preconditions / Affected

You are exposed if you installed any @mastra package, or anything depending on one, into a fresh or updated tree on or after June 17, 2026. A pre-existing lockfile that never re-resolved is not hit. Note @mastra/node-speaker@0.1.1 was added later as compromised. A handful of packages were published above legitimate latest (e.g. @mastra/schema-compat@1.2.12, @mastra/react@1.0.1, @mastra/voice-playai@0.12.2), so a plain patch bump does not necessarily supersede them.

What to do

  • Treat any resolved compromised version as a host and wallet exposure event — rotate credentials and move wallet funds, not just reinstall.
  • Move to Mastra's forward-rolled clean releases (PR #18056): @mastra/core@1.42.1, mastra@1.13.1, create-mastra@1.13.1. Note @mastra/core latest was also reverted to a clean 1.42.0.
  • For the over-published packages, Mastra used explicit higher pins (PR #18060) rather than patch bumps — pin to those, don't rely on latest.
  • Hunt for IOCs: marker files ~/.pkg_history / ~/.pkg_logs, connections to 23.254.164.92 and 23.254.164.123, and any lockfile entry for easy-day-js (1.11.21 or 1.11.22).

Caveats

Package-count reporting ranged from 80 to 144; anchor on the vendor's own figure of 142 publishable packages. easy-day-js has been removed from npm and ehindero is no longer a scope owner, but that does not remediate already-installed hosts.

Organisations named here

  • easy-day-js
  • SNYK-JS-EASYDAYJS-17353313

Technologies named here

  • @mastra/core
  • Snyk
  • npm ci
  • mastra
  • npm config set ignore-scripts true
  • create-mastra
  • mastracode
  • @mastra/* npm scope
  • @mastra/node-speaker
  • @mastra/schema-compat
  • @mastra/react
  • @mastra/voice-playai
  • easy-day-js
  • npm
  • Node.js
  • PowerShell
  • systemd
  • MetaMask

Techniques named here

  • Stale/dormant maintainer credential abuse
  • Package impersonation / typosquatting
  • Semver caret-range trick
  • Malicious postinstall script
  • TLS certificate validation bypass
  • Second-stage payload download and detached execution
  • Anti-forensic self-deletion
  • Marker file tracking
  • Persistence via OS-native mechanisms
  • Cryptocurrency wallet and browser data theft
  • C2 beaconing over self-signed TLS

Threat actors named here

  • Sapphire Sleet
  • ehindero
  • Mini Shai-Hulud
  • BlueNoroff