Skip to content

Back to the catalog

Mastra npm Supply Chain Attack: 140+ Packages Backdoored via easy-day-js Typosquat
stepsecurity.iowriteup

Mastra npm Supply Chain Attack: 140+ Packages Backdoored via easy-day-js Typosquat

StepSecurity documents the Mastra AI framework npm supply-chain attack: attacker sergey2016 published easy-day-js, a typosquat clone of dayjs, then added it as a dependency across 140+ @mastra packages after compromising the org's npm credentials. The malicious 1.11.22 version's postinstall hook ran an obfuscated dropper (setup.cjs) that disabled TLS verification, beaconed the install path, fetched a stage-2 payload from a hardcoded C2, spawned it detached, and self-deleted to erase forensic traces; StepSecurity's Harden Runner blocked the C2 callout in a controlled GitHub Actions test, preventing credential exfiltration of LLM/cloud API keys.

TL;DR Mastra npm org compromised to inject the dayjs-typosquat easy-day-js into 140+ packages, whose postinstall dropper self-deletes after fetching a C2 stage-2 payload; StepSecurity's Harden Runner blocked the callout in testing.
Document

What it is

An active npm supply-chain attack (disclosed June 17, 2026) against the @mastra AI-framework organization. An attacker compromised @mastra org credentials and added easy-day-js — a typosquat of dayjs — as a production dependency to 140+ packages. The malicious payload lives in easy-day-js@1.11.22; the dependency injected into @mastra packages was actually the clean 1.11.21. The page names the publishing account (sergey2016) and the disclosure thread: github.com/mastra-ai/mastra/issues/18045.

How it works

The version-resolution trick is the core mechanism the summary understates: @mastra packages pin "easy-day-js": "^1.11.21", so the injected dependency was clean at injection time. Publishing malicious 1.11.22 later means every fresh install auto-pulls the payload with no further change to @mastra packages. 1.11.22 is identical to 1.11.21 plus setup.cjs (4,572 bytes) and "postinstall": "node setup.cjs --no-warnings" (the flag suppresses Node warnings). setup.cjs is obfuscated with a custom-alphabet Base64 scheme backed by a 40-element string array that must be rotated 34 positions before an arithmetic integrity check passes — specifically to defeat static analyzers that read the array before rotation.

On install the dropper sets NODE_TLS_REJECT_UNAUTHORIZED = '0', writes beacon files .pkg_history and .pkg_logs to the temp dir, fetches stage-2 over TLS-disabled HTTPS, writes it to a random 12-byte-hex .js file in tmp, spawns it detached (stdio:'ignore', windowsHide:true, .unref()), then fs.rmSync(__filename) self-deletes.

Preconditions / Affected

Any environment that ran npm install of an @mastra package on/after June 17, 2026 (01:12 UTC). Because installs auto-resolve ^1.11.21, a clean lockfile from before is your protection; a fresh install is not. The page: "If you installed any @mastra package today, treat your environment as compromised."

What to do — IOCs

Hunt for these indicators (from the dropper source):

Stage-2 URL:  https://23.254.164.92:8000/update/49890878
Stage-2 C2:   23.254.164.123:443
Temp beacons: <os.tmpdir>/.pkg_history   (contains dropper __dirname)
              <os.tmpdir>/.pkg_logs
Malicious pkg: easy-day-js@1.11.22 (setup.cjs, 4572 bytes)
Publisher:     npm user sergey2016

The self-delete removes setup.cjs, but the tmp beacon files and the random-named .js stage-2 file persist — check tmp and outbound connections to 23.254.164.92/.123.

Caveats

This is an ongoing attack: the page states additional @mastra packages were being compromised as it was published, so the "140+" count and package list are not final. The fetched text is truncated mid-sentence during the evasion analysis, and stage-2 payload behavior is not described — only that it is fetched and run with the C2 host:port as an argument.

Organisations named here

  • easy-day-js

Technologies named here

  • Mastra AI framework
  • StepSecurity Harden-Runner
  • easy-day-js
  • StepSecurity Secure Registry
  • StepSecurity Dev Machine Guard
  • @mastra/core
  • dayjs
  • npm Package Cooldown Check
  • NPM Package Compromised Updates Check
  • @vapi-ai/server-sdk
  • npm Package Search
  • ai-sdk-ollama
  • jagreehal package family
  • StepSecurity Threat Center
  • npm
  • Node.js
  • GitHub Actions
  • StepSecurity
  • TypeScript
  • mastra

Techniques named here

  • npm typosquatting
  • Pre-positioning with a clean bait package
  • Semver range exploitation
  • npm postinstall hook dropper
  • Supply chain organization compromise / mass publish
  • Multi-layer code obfuscation
  • TLS certificate verification bypass
  • Host beaconing
  • Staged payload delivery
  • Detached background process execution
  • Anti-forensic self-deletion
  • Credential/environment variable harvesting
  • Phantom Gyp

Threat actors named here

  • sergey2016
  • Phantom Gyp technique
  • Miasma Campaign
  • Miasma