On 17 June 2026, someone took over the @mastra namespace on npm and, within minutes, published more than 140 fresh versions of packages belonging to this popular framework for building artificial intelligence applications. At first glance, none of those packages carried malicious code. The trap sat one level deeper, inside a dependency that had been added without fanfare.
What turns this into a lesson rather than a footnote is its reach. The affected packages accounted for over 1.1 million weekly downloads, according to analysis by JFrog Security Research, and the payload ran before any developer had even used the package, during installation itself. There was no CVE and no remote exploit. There was a forgotten maintainer account and an install hook.
What actually happened
The way in was not a vulnerability but a live credential nobody had revoked. The attackers used the "ehindero" account, belonging to a former Mastra contributor whose namespace access remained active long after they stopped contributing, as reported by The Hacker News. From that account they mass-published more than 140 packages across the @mastra scope in a very short window.
The clever part is that the Mastra packages themselves stayed clean. Anyone reviewing their source would have found nothing odd. The malicious behaviour was pushed down into a new dependency called easy-day-js, a clone of the well-known dayjs date library, added to each package's dependency list. It is a textbook supply chain attack: hide the harm where nobody looks, in the dependency of a dependency.
It is no accident that the target was a framework for building AI applications. The AI development ecosystem is growing fast, moves a great deal of money and drags along enormous dependency graphs, which makes it attractive ground for campaigns like this. Anyone working on AI security should assume that the supply chain of their tooling is part of the threat model.
The technical anatomy: it all happens in postinstall
The key component is the npm postinstall hook, an instruction that runs automatically right after a package is installed, with no further action from the developer. These hooks exist for legitimate reasons, such as compiling native modules, but they are also a code-execution doorway that many organisations never watch.
easy-day-js abused that hook with a clean and effective versioning trick. Version 1.11.21 was an innocent copy of dayjs, with no install hooks. Version 1.11.22, published as "latest", added the postinstall hook that launched the malicious code. Because the dependency was declared with a loose range (the familiar npm caret), a normal install resolved to 1.11.22 and triggered the payload, as documented by StepSecurity.
| Version | Postinstall hook | Behaviour |
|---|---|---|
| 1.11.21 | No | Clean copy of dayjs, no malicious activity |
| 1.11.22 (latest) | Yes | Runs setup.cjs and downloads the second stage |
Source: technical analysis by StepSecurity and JFrog (June 2026).
The hook executed an obfuscated file, setup.cjs, that followed a recognisable sequence: it disabled TLS certificate verification to avoid inspection, dropped beacon markers in temporary directories, fetched a second stage from the attacker's command and control infrastructure, spawned it as a detached background process and finally deleted itself to remove forensic traces.
The second stage was a cross-platform remote access trojan able to operate on Windows, macOS and Linux. Its documented capabilities included stealing browsing history and extracting data from more than 160 browser extensions tied to cryptocurrency wallets, as reported by The Hacker News and SC Media. JFrog has catalogued the campaign under the identifier XRAY-1004962.
The theft of cryptocurrency wallets points to a financial motive. Some analysts have noted technique overlaps with North Korea-linked groups such as BlueNoroff or Sapphire Sleet, according to The Hacker News, but firm attribution remains open. It is wiser to focus on what is confirmed: the delivery method, the reach and the capabilities of the trojan.
Why traditional controls miss it
This incident is uncomfortable precisely because it sidesteps much of the standard defensive toolkit. It is worth understanding why.
- There is no CVE to look for. A vulnerability management programme compares dependencies against catalogues of known flaws. Here there was no flaw: there was a legitimate package turned into a weapon. There is no identifier to match.
- The parent package was clean. A surface review of the Mastra package revealed nothing; the harm lived in a transitive dependency. If you do not inspect the full graph, you do not see it.
- It runs before any test. Postinstall runs during installation, with the user's permissions, both on the developer's laptop and on continuous integration servers. By the time the code reaches review, the machine is already compromised.
- Maintainer MFA would not have stopped it. This was not a stolen password but an authorised, forgotten contributor account whose namespace access was never revoked. The underlying problem was privilege management, not authentication.
Operational detection
If you build software or run npm installs across your organisation, there are concrete signals you can watch without exotic tooling.
- Outbound traffic during installation. An install command should not open connections to external domains beyond the package registry. A beacon leaving a continuous integration server is an anomaly that warrants an immediate alert.
- Endpoint detection telemetry. Look for node or npm processes spawning detached child processes, writing to temporary directories and generating traffic with TLS verification disabled.
- Lockfile diffs. Review every change to package-lock.json during code review: the sudden appearance of a new transitive dependency such as easy-day-js is exactly the signal to hunt for. A well-designed threat hunting routine starts from hypotheses like this one.
- Indicators of compromise. Check whether easy-day-js appears among your dependencies, search for beacon markers in temporary directories and cross-reference your findings with JFrog's XRAY-1004962 entry. The published indicators of compromise are your starting point.
If you find traces of the malicious dependency on a workstation or build server, treat it as an incident: isolate the host, rotate any credentials and wallets that may have been exposed and, where the scope justifies it, bring in digital forensics to reconstruct what happened. The dropper's self-deletion complicates the investigation, but telemetry captured before the deletion usually leaves a trail.
Concrete indicators to look for
As a starting point for a quick review, these are the documented traces of the campaign:
- The easy-day-js dependency present in the dependency tree, particularly version 1.11.22.
- Outbound connections during installation with TLS certificate verification disabled.
- Beacon markers written to temporary directories during or right after an npm install.
- node or npm processes spawning detached child processes in the background.
- The obfuscated setup.cjs file, which self-deletes after running; cross-reference your findings with JFrog's XRAY-1004962 entry.
Practical defence
The good news is that the countermeasures are concrete and, in large part, already available in the package manager itself.
- Disable install scripts by default. Use the option to ignore scripts wherever it is viable. npm v12 already disables them by default, and managers such as Bun block them unless an allow-list permits them, according to Rescana and Mondoo.
- Install reproducibly. Use clean installs from a committed lockfile and pin exact versions for your most sensitive dependencies, rather than open ranges that resolve to whatever was published last.
- Require verifiable provenance. npm lets a package sign its provenance and prove it was published from a specific integration pipeline. Verify those signatures and block downloads that lack them.
- Isolate the install. Run installs in ephemeral environments with no internet egress except to the registry, using an allow-list of domains. A trojan that cannot reach its command and control server loses half its usefulness.
- Put a firewall in front of your dependencies. An internal proxy registry, with quarantine for new versions and behavioural analysis, gives you room to spot anomalous publishes before they reach your teams.
- Revoke dormant access. The root cause was a forgotten contributor account. Apply least privilege on the publishing side too: review who can publish to your namespaces and remove access from anyone who no longer contributes. This ties directly to third-party risk management.
- Keep a dependency inventory. An up-to-date SBOM lets you answer the question "do we ship easy-day-js?" in minutes rather than after days of manual searching.
What it means for NIS2 and DORA
For a European organisation, this kind of incident is not only a technical problem: it bears directly on the supply chain security obligations of NIS2 and the ICT third-party risk management required by DORA.
If you develop software, the dependencies you incorporate travel all the way to your customers, and a compromised component reaching production can trigger the incident notification deadlines both regimes impose. Demonstrating that you control your dependency graph, that you keep an inventory and that you have incident response capability is exactly the kind of evidence these frameworks ask for.
The attack surface nobody chose
The most uncomfortable lesson from easy-day-js is that you can run an impeccable patching programme and still be compromised by a date library you never chose to install. The dependency graph is attack surface, just as seriously as an open port or an unpatched server.
The point is not to stop using open source, which is not realistic today, but to treat it with the same discipline as any other supplier: know what comes in, control how it comes in and be able to react quickly when something goes wrong. To place this incident within a broader strategy, we have collected five lessons for the CISO on the digital supply chain.