Get a Demo
Under Attack?
Security Feed - Mastra

Mastra Supply Chain Compromise: easy-day-js Dropper Pulls a Cross-Platform RAT Into @mastra Installs 

<br />
<b>Warning</b>:  Undefined variable $photo in <b>/nas/content/live/landing173/wp-content/themes/bricks/includes/elements/code.php(236) : eval()'d code</b> on line <b>33</b><br />
<br />
<b>Warning</b>:  Trying to access array offset on value of type null in <b>/nas/content/live/landing173/wp-content/themes/bricks/includes/elements/code.php(236) : eval()'d code</b> on line <b>33</b><br />
Guy Gilad June 17, 2026

Executive Summary

On June 17 2026, a coordinated supply chain attack pushed a malicious easy-day-js package into the dependency tree of the entire @mastra/* npm organization. Any npm install for a compromised @mastra/* package pulls [email protected], which runs a postinstall dropper, downloads a cross-platform RAT, installing persistent backdoors on macOS, Linux, and Windows. 

The Mastra ecosystem has more than a million weekly npm downloads, putting a large surface of developer machines and CI runners at risk.

The Compromise

The attack played out in two stages, run from two different npm accounts.

First, on June 16, an attacker using the account [email protected] published [email protected]. It looked like a harmless typosquat of the popular dayjs library. In reality, the code was an exact copy of dayjs with only the package.json changed. For the next 18 hours the package sat in the registry looking like any other quiet utility, attracting no installs and no attention.

Then, on June 17 at 01:01 UTC, the same attacker published [email protected]. This release was not harmless. It carried a postinstall script and an obfuscated dropper called setup.cjs.

Fourteen minutes later the attack pivoted. A second npm account, this one belonging to a legitimate Mastra maintainer ([email protected]), was used to republish every current @mastra/* package with one quiet change: a new dependency on "easy-day-js": "^1.11.21". Because npm resolves the caret range to the latest matching version, every fresh install of a touched @mastra/* package now pulls the armed 1.11.22 along with it.

At the time of writing, The package is live on the npm registry, also the C2 infrastructure is also active.

Which Packages Are Affected?

The injected dependency was published to more than a dozen @mastra/* packages, covering the broader Mastra ecosystem of 140+ packages. Known compromised versions include:

The last clean release of each package is the patch immediately preceding the affected version. Any developer workstation or CI runner that ran a fresh install or a lockfile-free npm i of an affected package since 2026-06-17 01:15 UTC should be treated as potentially compromised.

How to Check if Your System Is Compromised

  • Lockfile search: grep -r "easy-day-js" package-lock.json yarn.lock pnpm-lock.yaml
  • Dropper tmpdir markers: ls -la “$TMPDIR/.pkg_history” “$TMPDIR/.pkg_logs” 2>/dev/null
  • macOS persistence: ls ~/Library/NodePackages/ ~/Library/LaunchAgents/com.nvm.protocal.plist 2>/dev/null
  • Linux persistence: systemctl –user status nvmconf.service 2>/dev/null
  • Windows persistence: reg query HKCU\Software\Microsoft\Windows\CurrentVersion\Run /v NvmProtocal
  • Network: search DNS, egress proxy, and EDR logs for connections to 23.254.164.92 or 23.254.164.123, or the spoofed beacon UA mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0).

How Does the Attack Work?

  1. npm install of any compromised @mastra/* package resolves the caret range and pulls [email protected].
  2. npm runs the package’s postinstall script, which executes node setup.cjs –no-warnings.
  3. setup.cjs sets NODE_TLS_REJECT_UNAUTHORIZED=0, writes two marker files in $TMPDIR (.pkg_history, .pkg_logs), then fetches the stage-2 payload from https://23.254.164.92:8000/update/49890878 with Node’s default User-Agent. 
  4. The response is written to a random 12-character hex .js file in $TMPDIR, then spawned as a detached child process with 23.254.164.123:443 passed as argv[2].
  5. setup.cjs deletes itself with fs.rmSync(__filename) for anti-forensics.
  6. Stage-2 is a 41 KB obfuscated cross-platform RAT. On startup it collects installed applications, running processes, browser history domains from Chrome, Brave, and Edge, and a hit-list of 166 crypto wallet browser extension IDs including MetaMask, Phantom, Coinbase Wallet, Trust Wallet, Keplr, and TronLink.
  7. The collected data is sent to C2 as base64-wrapped JSON over application/x-www-form-urlencoded – a deliberate choice that bypasses JSON-aware WAF.
  8. The implant waits for a tpcsr command before running any stage-3 payload. The operator manually reviews each victim and decides whether to proceed – victims without wallets or interesting dev tooling may never see a follow-up.

    The stage-3 payload URL is decoupled from the C2 address, and a separate gfcm command lets the operator migrate the implant to a new PrimaryUrl at any time. Existing infections survive a takedown of the current C2.

Indicators of Compromise

  • Stage-2 source: https://23.254.164.92:8000/update/49890878
  • Beacon and exfil: https://23.254.164.123:443/49890878 (POST, base64 JSON in form-urlencoded body)
  • Spoofed beacon User-Agent: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0)
  • C2 CIDR: 23.254.164.0/24
  • TLS cert issuer: Caddy Local Authority – ECC Intermediate, 12-hour validity window
  • macOS persistence: ~/Library/NodePackages/protocal.cjs, ~/Library/LaunchAgents/com.nvm.protocal.plist, label com.nvm.protocal
  • Linux persistence: ~/.config/systemd/nvmconf/protocal.cjs, service nvmconf.service
  • Windows persistence: C:\ProgramData\NodePackages\protocal.cjs, Run key HKCU\Software\Microsoft\Windows\CurrentVersion\Run\NvmProtocal
  • Config file (all platforms): config.json containing UID, PrimaryUrl, Cycle
  • Tmpdir markers: .pkg_history, .pkg_logs, random 12-hex .js files
  • Author fingerprint: the misspelling protocal appears across every persistence mechanism

Mitigation and Patching

  1. Pin every @mastra/* package to the last clean version (the patch immediately preceding the affected version above). Block easy-day-js outright in your package manager policy.
  2. Treat any developer workstation or CI runner that ran a fresh install of an affected @mastra/* package since 2026-06-17 01:15 UTC as potentially compromised. Rotate every credential reachable from the shell environment – the stage-3 shell runner uses /bin/zsh -s, inheriting ~/.zshrc, so AWS_ACCESS_KEY_ID, GITHUB_TOKEN, npm tokens, and similar are all in scope.
  3. On macOS, delete the persistence files before killing the process. Order matters:

rm -f ~/Library/NodePackages/protocal.cjs

rm -f ~/Library/LaunchAgents/com.nvm.protocal.plist

rm -f ~/Library/NodePackages/config.json

pkill -f protocal.cjs

rm -f “$TMPDIR/.pkg_history” “$TMPDIR/.pkg_logs”

  1. Block egress to 23.254.164.92 and 23.254.164.123 at the firewall and add the C2 IPs plus the spoofed IE8/XP User-Agent to your network detection ruleset. Multi-tenant CI environments first, isolated developer laptops after.

How Upwind Helps

Upwind actively scans for in-the-wild supply chain campaigns and continuously monitors customer runtime data. That combination is how the initial @mastra/* republish was caught within hours of the publish window, well before any public IOC list existed.
Upwind’s runtime telemetry surfaced the malware through anomalous behavior on customer right as it was executed.

Upwind also maps every instance of the affected packages across customer environments so teams can prioritize and remediate the impacted workloads.

Contents

Further Reading

KSPM-Agentless-Scanning

Complete KSPM: From Pull Request to Production Runtime

Kubernetes environments move fast. Workloads appear and disappear, container images change continuously, services are exposed, permissions evolve, and development teams deploy updates throughout the day. But most cloud security platforms force practitioners to investigate Kubernetes risk through interfaces designed for the broader cloud, leaving teams to manually filter the noise before they can begin investigating…
Upwind MCP Server

Revolutionizing Security Investigations with the Upwind MCP Server

Frontier AI models combined with a rampant rate of new critical vulnerabilities mean speed and context are everything. When a critical production service starts behaving suspiciously, every second spent jumping between different tools and dashboards is a second lost to a potential attacker. At Upwind, we are excited to introduce a game-changer for security teams:…
Security Feed - Threat

No npm Token Required: Inside the AsyncAPI Supply Chain Attack

Executive Summary Upwind identified a critical supply chain compromise across five npm packages in the @asyncapi scope, published on July 14, 2026 via two separate branch compromises in two GitHub repositories. The attacker never touched an npm token. They abused each project's own CI pipeline through GitHub Actions OIDC to publish the malicious packages. The…