Safeguard
Software Supply Chain Security

A forgotten contributor account compromised the Mastra npm scope

A dormant npm account with unrevoked publish rights let attackers trojanize 144 @mastra packages in 88 minutes, dropping a crypto-wallet RAT tied to Sapphire Sleet.

Safeguard Research Team
Research
6 min read

On June 17, 2026, between 01:12 and 02:39 UTC, an attacker used a single dormant npm account to republish 142 packages across the entire @mastra scope — plus the top-level mastra and create-mastra convenience packages, for 144 packages in total. The account, published under the username ehindero, had last pushed legitimate alpha builds of @mastra/core between November 2024 and February 2025, then gone quiet. Its publish rights to the scope were never revoked. In an 88-minute automated run, the attacker injected a single new dependency, a typosquat of dayjs called easy-day-js, into every republished package. Because the packages pinned that dependency with a caret range, npm's own semver resolution pulled the malicious version onto every machine that ran npm install during the window. @mastra/core alone sees roughly 918,000 weekly downloads, and the framework's combined weekly install volume tops 1.1 million.

How did one npm account take down an entire package scope?

npm does not expire publish permissions when a maintainer goes inactive, and that gap is what turned one stale credential into scope-wide compromise. The ehindero account had legitimate history in the @mastra organization — it published early alpha builds of @mastra/core in late 2024 and early 2025 before going dormant for well over a year. Nothing about the account was flagged as unusual because, from npm's perspective, nothing had changed: it still held the same publish scope it had been granted during active development. When the credential was compromised, likely through session-token theft or password reuse rather than any flaw in Mastra's own code, the attacker inherited blanket write access to every package under the @mastra namespace with no additional approval step required. This is not a Mastra-specific flaw; it is how npm scopes work by default. Any project that has ever granted scope-wide publish rights to a contributor who later left, went inactive, or stopped checking their email carries the same latent exposure until someone explicitly revokes it.

What did the malicious payload actually do once installed?

The payload, delivered through a postinstall script named setup.cjs in the trojanized easy-day-js dependency, disabled TLS certificate validation, fetched a second-stage binary from attacker infrastructure, and then deleted itself to hide the install trail. Specifically, the script set NODE_TLS_REJECT_UNAUTHORIZED=0 so it could pull its next stage from an IP-literal endpoint (23.254.164.92:8000) behind a self-signed certificate without triggering a handshake failure. It wrote marker files into the user's home directory, spawned the downloaded payload as a detached background process with stdio suppressed so it would survive the parent install process exiting, and then removed setup.cjs from disk with fs.rmSync. The second-stage RAT was built to enumerate roughly 166 cryptocurrency wallet browser extensions across Chrome, Brave, and Edge, establish persistence disguised as Node version-manager or systemd tooling, and beacon to command-and-control infrastructure roughly every ten minutes. None of this required a developer to do anything beyond running a routine npm install on a project that depended on any of the 144 affected packages.

How did the attacker make the malicious version look trustworthy?

The attacker published a clean, functional version of easy-day-js a full day before weaponizing it, so the package already had a working install history when the mass-republish began. easy-day-js@1.11.21 went live on June 16, 2026, behaving exactly like the dayjs utility it was typosquatting — no red flags, no unusual behavior, nothing for automated scanners or a wary developer to catch. Then, in the minutes before the 01:12 UTC republish wave started, the attacker pushed easy-day-js@1.11.22 with the malicious postinstall hook baked in. Because the trojanized @mastra packages had pinned easy-day-js with a caret range like ^1.11.21, every fresh install or CI run during the attack window silently resolved to the new, malicious patch version without any package.json change, any pull request, or any visible diff in the dependent projects' own repositories. This is the same class of trick used in prior high-profile npm incidents: establish a benign publish history first, then flip the payload in a version bump too small for most humans to scrutinize.

Who is responsible, and why did the timeline matter?

Microsoft Threat Intelligence attributed the campaign on June 19, 2026, with high confidence to Sapphire Sleet, a North Korean state-linked actor also tracked publicly as BlueNoroff and APT38. The group has a documented history of targeting cryptocurrency infrastructure and developer tooling, which lines up with the RAT's focus on wallet extensions rather than generic data exfiltration. The 88-minute automated republish window — 01:12 to 02:39 UTC on June 17 — was fast enough that manual review had essentially no chance of catching it before packages were live and being pulled by dependents worldwide. Detection and containment relied on downstream monitoring rather than the registry itself flagging the activity in real time; some analyses put the time-to-detection at just over two minutes after the first malicious publish, but stopping propagation across a scope that size, once semver ranges start resolving, is a different problem than detecting the first bad publish.

What should teams that depend on Mastra packages do now?

Any environment that ran npm install, npm ci, or an equivalent against a @mastra package after June 16, 2026 should be treated as potentially compromised until proven otherwise. That means rolling back to pinned, pre-incident package versions rather than trusting a re-published "clean" tag, and rotating every credential that could have been accessible on affected machines — npm tokens, GitHub tokens, cloud provider keys, LLM API keys, CI/CD secrets, SSH keys, and database credentials. Teams should also hunt for the specific indicators tied to this campaign: marker files such as ~/.pkg_history and ~/.pkg_logs, detached Node child processes spawned during the install window, and outbound connections to 23.254.164.92:8000 or 23.254.164.123:443. Because the dropper masqueraded as legitimate Node tooling for persistence, a simple process list review is not sufficient; teams need to check systemd units, LaunchAgents, and scheduled tasks created around the incident window. Longer term, the practical fix is boring but effective: audit every npm scope your organization depends on for maintainers who haven't published in the last 12 months, and treat "still has publish rights" as equivalent to "still has production access" for the purposes of offboarding.

How Safeguard Helps

Safeguard's reachability analysis is what separates "we depend on a compromised package" from "our running code actually calls the vulnerable path," so teams can triage which of their services touched the trojanized easy-day-js install hook versus which merely listed a @mastra package as an unused transitive dependency. Griffin AI, Safeguard's detection engine, correlates anomalous publish behavior, timing patterns, and dependency-graph changes like the 88-minute mass republish and caret-range payload swap seen here, surfacing the kind of scope-wide takeover that signature-based scanning alone tends to miss until it's already in a threat feed. Safeguard continuously generates and ingests SBOMs across your fleet, so when an incident like this breaks, you can query exactly which services, containers, and build artifacts pulled in any of the 144 affected packages or the easy-day-js typosquat in minutes rather than days. And where remediation is needed, Safeguard opens auto-fix pull requests that pin dependencies to the last known-good, provenance-backed version and remove vulnerable ranges, so the fix ships as fast as the compromise did.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.