For a year, the security conversation around AI agents has been about the runtime. We argue about prompt injection, the lethal trifecta, tool allowlists, permission prompts, and whether your container is really a sandbox. All of it governs what the agent does once it is running.

The most consequential agent-security incident of June 2026 never touched the runtime. It happened during npm install.

What happened#

On June 17, 2026, an attacker republished more than 140 packages across the mastra and @mastra npm scopes — the Mastra AI agent framework — in a fully automated 88-minute burst between 01:12 and 02:39 UTC. Every republished package got one new dependency quietly grafted on: easy-day-js, a typosquat of the ubiquitous dayjs date library.

The choreography was patient. Per Microsoft's timeline, a clean easy-day-js@1.11.21 was published a day earlier to build credibility. Minutes before the mass republish, the attacker shipped a weaponized 1.11.22. Because the compromised packages pinned ^1.11.21, npm's semver resolution did the rest — every fresh install obediently pulled the malicious patch.

Installing any affected package ran a 4,572-byte setup.cjs postinstall dropper. It disabled TLS certificate verification, pulled a second-stage Node implant from a command-and-control host at 23.254.164[.]92:8000, then deleted itself.

There was no CVE. Mastra's source code was never modified. As Snyk documented, the root cause was mundane and awful: a forgotten contributor account (ehindero) still held publish rights to the entire scope. One dormant credential, never revoked, was the whole attack surface.

Read the payload honestly#

It's tempting to say the malware "stole your API keys." Per Microsoft's analysis, that's not what the observed second stage actually did. It was a financially-motivated infostealer: it enumerated 166 cryptocurrency-wallet browser extensions (MetaMask, Phantom), scraped browser-history SQLite databases, and profiled the host. That fingerprint fits the attribution — Microsoft assessed with high confidence that this was Sapphire Sleet, a North Korean actor also tracked as BlueNoroff and APT38, which "primarily targets the financial sector."

So this particular crew went for wallets, not weights. But hold that thought against where the code ran.

The blind spot#

Every guardrail we've built for agents governs the agent. None of them was awake when this fired.

Here is the uncomfortable through-line. The dropper executed at install time, on a developer or CI machine, with that user's full privileges, before any agent process existed. Walk down the defenses agent teams have spent a year building, and check each one against this attack:

Now add the part that should keep agent builders up at night. An agent-framework package installs on the single machine that concentrates the most valuable secrets in modern software: model provider keys (ANTHROPIC_API_KEY, OPENAI_API_KEY), cloud credentials, and — increasingly — the agent's own issued identity. Sapphire Sleet chose wallets. A crew with a different mandate, sitting on the exact same foothold, chooses your inference budget and your production cloud role. The blast radius of an agent framework was never the agent. It's the install.

The postinstall era is ending — which is the tell#

The reason postinstall is such a reliable weapon is that npm has run dependency install scripts automatically for a decade. That's finally changing: npm v12, arriving in July 2026, disables preinstall/install/postinstall scripts by default. A one-line --ignore-scripts would have neutered this entire attack, and soon that's the default.

Don't read that as "solved." Read it as "the target moves." Attackers are already probing install-time execution paths that survive the change — abusing native-build config to trigger code without a lifecycle script, and injecting persistence into AI-assistant config files (.claude/, .cursor/) so a backdoor fires the next time a developer opens the project in their agentic IDE. The class of attack — run my code on the machine that holds the keys, outside the runtime you hardened — isn't going anywhere.

What to actually do#

Mastra responded correctly and fast: easy-day-js was pulled, ehindero lost ownership, and clean versions were forward-rolled (PR #18056) with the latest dist-tag moved past the poisoned builds. For your own stack:

The agent-security field spent a year learning to distrust what the model reads. The Mastra attack is a reminder to distrust what your package manager runs — because that code gets your keys without ever meeting your agent.