
Mastra npm Attack: 144 Packages Backdoored by North Korea
June 21, 2026
If you use Mastra to build AI agents, stop and check your installs right now. On June 17, an attacker hijacked a dormant maintainer account and backdoored 144 packages across the entire @mastra npm scope — and Microsoft has linked the attack to Sapphire Sleet, a North Korean state-sponsored group also known as BlueNoroff.
This isn't a typosquat scam targeting careless installs. It's a takeover of a legitimate, trusted scope that ships tens of millions of downloads a month, hitting exactly the kind of credentials AI development environments hold: cloud keys, LLM API keys, and crypto wallets.
What Happened, Minute by Minute
The setup started a day early. On June 16 at 07:05 UTC, an npm user called sergey2016 published easy-day-js@1.11.21 — a clean, fully functional copy of the popular dayjs date library. No malicious code. Its only job was to look legitimate: same version numbering, same author metadata, same license, same keywords as the real dayjs.
Then, on June 17 at 01:01 UTC, the same account published easy-day-js@1.11.22. This version added a postinstall hook that ran an obfuscated dropper.
Eleven minutes later, an attacker using the ehindero npm account began republishing the entire @mastra scope. Over the next 88 minutes, 140+ packages — including @mastra/core, mastra, create-mastra, and infrastructure packages like @mastra/mcp and @mastra/pg — were pushed with one new line added to each package.json: a dependency on easy-day-js, pinned with a caret range (^1.11.21).
That caret range is the entire trick. npm resolves caret ranges to the newest matching version at install time, not the version actually written in the file. So npm install always pulled the malicious 1.11.22, even though the pinned baseline looked clean.
Why a Caret Range Did All the Damage
This is worth sitting with, because it's not a code vulnerability. Mastra's actual source code was never touched. The attacker didn't need to write convincing malicious application logic — they needed publish access to one scope and one malicious dependency to fan a payload out across 140+ packages in a single automated wave.
The postinstall hook ran setup.cjs, an obfuscated dropper that disabled TLS certificate verification, fetched a second-stage payload from a raw IP address instead of a domain, and ran it as a detached, hidden background process. According to Microsoft's writeup, that second stage delivered a PowerShell backdoor and established further persistence on infected machines.
The final payload is a cross-platform infostealer and cryptocurrency wallet thief, confirmed to run on Windows, macOS, and Linux.
How a 16-Month-Dormant Account Took Down a Trusted Scope
The access vector is the real lesson here. The ehindero account was a real former Mastra contributor who published legitimate alpha versions of @mastra/core between November 2024 and February 2025, then went dormant. Its scope publish access was never revoked.
npm has no mechanism to expire publish permissions based on inactivity. A 16-month-old, completely unused credential was enough to push malicious code to the entire namespace. The account's email had been quietly swapped to a tutamail.com address matching the pattern of the sergey2016 account that staged the bait package — a clear signal of account takeover rather than insider action.
Each malicious package also dropped the SLSA provenance attestation that Mastra's CI pipeline normally generates. That gap was visible to anyone checking: clean versions showed a verified GitHub Actions publisher, while the malicious versions showed an unverified, unattested one.
Microsoft's Attribution: Sapphire Sleet
Microsoft Threat Intelligence assessed with high confidence that this campaign is attributable to Sapphire Sleet, the threat actor more widely known as BlueNoroff — a North Korean state-sponsored group with a long track record of targeting cryptocurrency and developer infrastructure.
Researchers at Socket also noted that the same loader sample had appeared on public malware sandboxes around May 29, roughly 19 days before this attack — meaning this was reused, tested tooling, not improvised malware.
Is Your Project Affected?
Confirmed clean versions: mastra 1.13.0 and earlier, @mastra/core 1.42.0 and earlier.
Compromised: Any @mastra/* package version published after the June 17, 2026 01:01 UTC window. The attack hit the full scope in roughly download order — core packages, infrastructure connectors, database integrations, and provider SDKs were all republished.
Check for the indicator package directly: search your node_modules and lockfiles for easy-day-js. If it's there, in any version, treat the machine as compromised.
What to Do Right Now
If you installed any @mastra package, or anything depending on one, on or after June 17, 2026:
Treat the machine as compromised. Don't just delete node_modules and reinstall — assume credentials on that machine were already exposed.
Rotate everything reachable from that environment. Cloud provider keys, LLM API keys (OpenAI, Anthropic, Google), database credentials, npm tokens, GitHub tokens, and any cryptocurrency wallets accessible from that machine or CI runner.
Check for IOC artifacts. Look for $TMPDIR/.pkg_history, $TMPDIR/.pkg_logs, and randomly named 24-character hex .js files in your home or temp directories.
Block the known C2 infrastructure. Microsoft's advisory lists 23.254.164[.]92 and 23.254.164[.]123 as C2 IPs tied to this campaign.
Roll back to clean versions. Mastra has forward-rolled clean releases — @mastra/core is back to a verified 1.42.0. Pin your dependencies explicitly rather than trusting caret ranges on anything touching credentials.
Install with --ignore-scripts as a standing defense. This specific attack relied entirely on a postinstall hook firing automatically. Disabling lifecycle scripts by default blocks that execution path outright, though it can break packages that legitimately need native builds.
Why This Keeps Happening to npm
This is the second major npm scope-takeover incident we've covered this month, and the pattern is identical: a trusted maintainer credential, no expiry on dormant access, and a caret-range dependency doing the dirty work instead of the visible package code. If you haven't already, it's worth reading our coverage of IronWorm and the Miasma worm campaign — different malware, same structural weakness in how npm handles trust and access over time.
Zero CVE was assigned to this incident, because there's no software vulnerability to patch. The fix isn't a security update — it's npm enforcing scope-access expiry, mandatory provenance, and stricter dependency pinning defaults. Until that changes, audit your dependency trees like the next supply chain attack is already staged and waiting on a stale account somewhere.
Sources: Microsoft Security Blog, StepSecurity, Snyk, SafeDep, Mend.io
Frequently Asked Questions
What is the Mastra npm attack?
On June 17, 2026, an attacker hijacked a dormant Mastra contributor's npm account and republished 144 packages across the @mastra scope, each with a malicious dependency called easy-day-js added. The dependency's postinstall hook downloaded and ran a cross-platform infostealer and cryptocurrency wallet thief.
Is the Mastra npm attack linked to North Korea?
Yes. Microsoft Threat Intelligence assessed with high confidence that the campaign is attributable to Sapphire Sleet (also known as BlueNoroff), a North Korean state-sponsored threat actor.
Which Mastra package versions are safe?
mastra version 1.13.0 and earlier, and @mastra/core version 1.42.0 and earlier, are confirmed unaffected. Any version published after 01:01 UTC on June 17, 2026 should be treated as potentially compromised until verified against Mastra's clean forward-rolled releases.
What should I do if I installed a compromised Mastra package?
Treat the affected machine as fully compromised. Rotate all credentials reachable from that environment — cloud keys, LLM API keys, database credentials, npm and GitHub tokens, and cryptocurrency wallets. Check for indicator files in your temp directory and roll back to verified clean package versions.