Microsoft on June 19 pinned a 140-package npm supply chain attack against the Mastra AI agent framework on Sapphire Sleet, a North Korean state group also tracked as BlueNoroff. The campaign used a single typosquatted dependency, easy-day-js, to reach developer credentials, LLM API keys, and browser-based crypto wallets, and it followed nearly the same playbook the same actor ran against the Axios npm package two months earlier.
The Mastra AI agent framework, an open-source TypeScript project for building AI agents, workflows, and retrieval pipelines, sits in environments that routinely hold credentials most other packages never see. The same installs typically carry LLM API keys for OpenAI, Anthropic, and Google, AWS and Azure credentials, and CI/CD tokens for GitHub and npm.
Microsoft Pins the Attack on North Korea
Microsoft Threat Intelligence updated its original June 17 write-up two days later, on June 19, 2026, with a high-confidence attribution to a North Korean state actor known for financial-sector targeting. The infrastructure and post-compromise tradecraft, including a PowerShell backdoor, Microsoft Defender exclusions, and a SYSTEM-context service implant, matched patterns Microsoft had already documented for the same group. The full technical walk-through, including the seven-phase attack chain, sits in the full breakdown of the npm postinstall attack chain.
Microsoft assesses with high confidence that this activity is attributable to Sapphire Sleet, a North Korean state actor that primarily targets the financial sector.
Microsoft named the actor in the same update, calling out the overlap with a separate npm supply chain compromise of Axios, a popular JavaScript HTTP client, in April 2026. That earlier campaign used a typosquat called plain-crypto-js in place of easy-day-js, and it hit the same Hostwinds infrastructure on port 8000 that showed up in the Mastra dropper. Aikido, in its own write-up, called the Mastra and Axios playbooks “nearly identical.”
A Stale Maintainer Account Opened the Door
The foothold was not a zero-day. Snyk’s analysis of the npm registry’s publish history shows the ehindero account was a real former Mastra contributor, with legitimate alpha releases of @mastra/core from late 2024 and early 2025, that went dormant and was never removed from the @mastra scope. The registry shows the account’s email was later changed to ehindero2016@tutamail.com, a sign of takeover rather than insider action. Snyk published the account-compromise analysis of the @mastra npm scope this week.
Project hygiene, not a zero-day, is the root cause. npm does not expire scope publish permissions on inactivity, so one stale maintainer credential was enough to push to every package in the scope.
From that one compromised account, the attacker drove an automated republish across the entire scope. StepSecurity’s runbook on the typosquat dropper behavior traces how fast the cascade ran:
- June 16, 2026, 07:05 UTC: easy-day-js@1.11.21 published as a clean, byte-for-byte copy of the legitimate dayjs library.
- June 17, 2026, 01:01 UTC: easy-day-js@1.11.22 published, adding a postinstall hook that runs setup.cjs.
- 01:12 UTC: First @mastra package republished (@mastra/schema-compat, roughly 1.23M weekly downloads).
- 01:15 to 01:30 UTC: Core, memory, server, observability, and deployer packages republished.
- 02:39 UTC: Last observed package (@mastra/dane) hits the registry, 88 minutes after the first.
Aikido put the final republished count at 141. Microsoft said 140+. Snyk counted “essentially the entire @mastra scope” and noted that Mastra’s own emergency response forward-rolled 142 publishable packages to clean versions.
The Typosquat That Looked Like a Date Library
easy-day-js was built to pass a casual review. Microsoft’s comparison of the two packages shows how thoroughly the attacker copied the legitimate project:
| Attribute | Legitimate dayjs | Malicious easy-day-js |
|---|---|---|
| Claimed author | iamkun | iamkun (impersonated) |
| Repository URL | github.com/iamkun/dayjs | github.com/iamkun/dayjs (copied) |
| Weekly downloads | 57,251,792 | Newly created |
| Version count | 89+ versions since 2018 | 2 versions (both June 16, 2026) |
| Postinstall script | None | node setup.cjs –no-warnings |
The only reliable giveaways were the npm maintainer (sergey2016, registered to sergey2016@tutamail.com, the same anonymous email provider used on the ehindero account) and the presence of setup.cjs in the tarball. dayjs is one of the most widely used date libraries in the JavaScript ecosystem, with 57,251,792 weekly downloads, and that name recognition is exactly why the attacker chose it.
What the Postinstall Hook Did in Five Steps
The attack worked because the malicious code ran at install time, with no import required. Aikido’s deobfuscated version of setup.cjs, captured in its write-up of the 141 republished packages in the @mastra scope, shows the dropper’s full sequence.
First, the script sets NODE_TLS_REJECT_UNAUTHORIZED=’0′, disabling certificate validation so it can reach a C2 server that uses a self-signed certificate. Second, it drops two marker files to the OS temp directory: .pkg_history, containing the install path of the compromised package, and .pkg_logs, with the package name XOR-encoded. Third, it issues a GET request to https://23.254.164[.]92:8000/update/49890878, a Hostwinds VPS, and reads the response body. Fourth, it writes the response to a randomly named .js file in the temp directory and spawns it as a fully detached, window-hidden Node.js process, with the address 23.254.164[.]123:443 passed as its first argument. Fifth, it deletes setup.cjs to remove the postinstall hook from the filesystem.
The second stage, a roughly 41 KB cross-platform Node.js tasking client, is where the actual collection happens. Aikido and Snyk both note that it targets more than 160 browser-based crypto wallet extensions, including MetaMask, Phantom, Coinbase Wallet, OKX, Keplr, and Solflare, alongside browser history, running processes, and installed application data, then exfiltrates the lot to the C2 at 23.254.164[.]123:443 roughly every 10 minutes. Persistence is installed in ways designed to blend in with normal Node tooling: a Windows Registry Run key called NvmProtocal, a macOS LaunchAgent labelled com.nvm.protocal, and a Linux systemd user unit named nvmconf.service.
The Real Target Was the Developer’s Whole Stack
Mastra’s package set is unusually credential-dense for a JavaScript framework, because its official integrations with OpenAI, Anthropic, vector databases, MCP servers, and cloud deployment targets put LLM API keys, cloud, and CI/CD secrets in scope by default. StepSecurity’s write-up lists the categories a typical Mastra install sits next to: LLM API keys for OpenAI, Anthropic, and Google; cloud provider credentials including AWS and Azure; database connection strings; and CI/CD and VCS tokens such as GITHUB_TOKEN and NPM_TOKEN.
A single npm install on a developer’s laptop or a CI runner can reach more than a poisoned package:
- Cloud keys that open production environments, not just one machine.
- npm and GitHub tokens that let the attacker publish more poisoned packages.
- LLM provider keys that can be resold or used to bill against the victim’s account.
- Browser-side wallet extensions that hold the developer’s personal funds.
- CI/CD secrets that propagate into every downstream artifact the build produces.
Microsoft confirmed that on systems where the implant reached the C2, Sapphire Sleet delivered a PowerShell backdoor from separate infrastructure and added Microsoft Defender exclusions, a tradecraft bundle Snyk and StepSecurity both read as consistent with a financial-extraction objective.
The Same Playbook Hit Axios Months Earlier
The Mastra attack is the second time in 2026 that the same North Korea-linked tradecraft landed on a high-traffic JavaScript package. Microsoft said Sapphire Sleet also compromised Axios in April 2026, a campaign that maps to the earlier Axios npm compromise traced to North Korean hackers. Aikido pointed out that the Axios dropper called back to a Hostwinds VPS on port 8000, the same provider and port the Mastra dropper used. In both cases, the attacker avoided modifying the target package’s own code and instead injected a single typosquatted dependency, staged a clean decoy version first, and let npm’s caret resolution pull the armed version at install time.
Microsoft’s decision to publish a high-confidence attribution on the Mastra campaign, with the post-compromise tradecraft, infrastructure overlap, and the April Axios compromise lined up, is the closest the security industry has come to a public blueprint for naming this specific North Korean supply chain operator.
The Lockfile Question and What Teams Should Do Now
Whether a given build was actually exposed comes down to the lockfile. Snyk’s analysis draws the line precisely: any project with a committed lockfile pinned to a pre-June 17 version of @mastra packages is likely fine, because npm ci reproduces the pinned tree and would not have pulled the malicious 1.11.22 release. Any project without a lockfile, with a loose range, or with a fresh install or lockfile regeneration on or after June 17, would have resolved easy-day-js to 1.11.22 and run the postinstall hook.
Earlier npm supply chain worm campaigns, including the Shai-Hulud 2.0 npm worm targeting cloud credentials, used the same pattern. Snyk’s safe rebuild path for the current Mastra exposure runs in this order:
- Upgrade to a clean @mastra version (e.g. @mastra/core@1.42.0) and regenerate the lockfile; do not pin downward to dodge the compromise.
- Remove easy-day-js from every dependency tree and lockfile; it should never legitimately appear.
- Rotate every credential the affected host could reach: cloud keys, npm and GitHub tokens, CI secrets, LLM provider keys, and SSH keys.
- Check CI logs for installs during the June 17 window and review developer machines for unusual Node.js processes and persistence entries.
- Search egress logs for connections to 23.254.164[.]92:8000 or 23.254.164[.]123, and rebuild affected environments from trusted images where practical.
Snyk also recommends disabling install scripts by default with npm config set ignore-scripts true, and requiring npm provenance on consumption, a step Mastra did not enforce on its own CI publishes, so a plain token could still push a new version without attestations.
Frequently Asked Questions
Who did Microsoft attribute the Mastra npm attack to?
Microsoft Threat Intelligence said on June 19, 2026 that it “assesses with high confidence” the campaign is the work of Sapphire Sleet, a North Korean state actor also known as BlueNoroff. The same group was linked by Microsoft to a separate npm supply chain compromise of Axios in April 2026.
How did the attacker compromise 140+ packages at once?
The attacker took over the ehindero npm account, a real former Mastra contributor whose scope access was never revoked, then used automated publishing to republish the entire @mastra scope with one added dependency: easy-day-js. Aikido counted 141 republished packages; Microsoft’s write-up says 140+.
What is easy-day-js and what did it do?
easy-day-js is a typosquat of the dayjs JavaScript date library. Version 1.11.22 added a postinstall hook that ran an obfuscated dropper, which disabled TLS verification, fetched a second-stage payload from a Hostwinds VPS, and spawned a long-running info-stealer and crypto-wallet-targeting RAT in the background. The dropper then deleted itself to remove forensic traces.
Was my project exposed?
A project is at risk only if a developer machine or CI runner resolved easy-day-js@1.11.22 during the June 17 exposure window, which is most likely if its lockfile was loose, missing, or regenerated on or after June 17, 2026. A project with a lockfile pinned to pre-incident @mastra versions would not have pulled the malicious release through npm ci. Snyk’s advisory SNYK-JS-EASYDAYJS-17353313 and Mastra’s remediation PR #18056 list the affected versions.
What should teams do now?
Remove compromised package versions, delete easy-day-js from dependency trees, rotate npm, GitHub, cloud, LLM, and CI/CD credentials, audit CI logs for installs during the exposure window, and rebuild affected environments from trusted images where practical. Snyk also recommends disabling install scripts by default and requiring npm provenance on consumption.








