
On June 17, 2026, an attacker with access to the @mastra npm organization published malicious new versions of 13 packages across the Mastra AI framework ecosystem. Each compromised package quietly added easy-day-js, a freshly created typosquat of the popular dayjs date library, as a production dependency. That package carried a postinstall hook that ran an obfuscated dropper, pulled a second-stage payload from attacker infrastructure, and then deleted itself to erase the evidence. The compromise was documented by StepSecurity, and the Mastra maintainers are tracking it in issue #18045.
This is a textbook npm supply chain attack, executed against the dependency tree of an AI agent framework. The mechanics are worth understanding in detail, because they explain why a dependency scan tells you the package is present but not whether the dropper actually ran in your environment. This post covers what happened, the full timeline, what the dropper does, the indicators of compromise, a first-hour runbook, and why answering the real question requires runtime evidence.
Attack Summary
| Field | Value |
|---|---|
| Disclosure date | June 17, 2026 |
| Affected ecosystem | @mastra npm organization (AI agent framework) |
| Compromised packages | 13 @mastra/* packages republished with a malicious dependency |
| Malicious dependency | easy-day-js (typosquat of dayjs) |
| Malicious version | [email protected] (bait version 1.11.21 published first) |
| Execution vector | postinstall hook running an obfuscated setup.cjs dropper |
| Stage-2 download | https://23.254.164.92:8000/update/49890878 |
| Stage-2 beacon | 23.254.164.123:443 |
| Attacker npm account | sergey2016 (published the typosquat) |
| Behavior | Disables TLS validation, beacons install path, runs detached payload, self-deletes |
| Likely objective | Harvesting LLM, cloud, and VCS credentials from developer and CI environments |
Mastra Sits Exactly Where the High-Value Secrets Live
Mastra is an open-source TypeScript framework for building AI agents, workflows, and RAG pipelines. Its packages integrate LLM providers like OpenAI, Anthropic, and Google, manage persistent memory, implement Model Context Protocol servers, and deploy AI workloads to cloud providers. In practice that means @mastra packages are installed in three places that matter to an attacker: developer laptops, CI/CD pipelines, and production AI services.
Those are exactly the environments that hold LLM API keys, cloud provider tokens, and database credentials. A compromise of the framework's dependency tree is not a compromise of one application. It is a foothold across every team that runs a fresh install while the malicious versions were live.
How the Attack Unfolded
The campaign ran in two phases. The first built a credible decoy. The second weaponized it across the organization in 36 minutes.
Phase 1: A typosquat built to look real (June 16)
At 07:05 UTC on June 16, the npm account sergey2016 published [email protected], a clean copy of the legitimate dayjs library with no postinstall hook and no malicious files. The metadata was crafted to pass a casual review: it copied dayjs's author field (iamkun), homepage (https://day.js.org), repository URL, keywords, and even matched the real [email protected] version lineage. This was bait, and it was the version referenced by the @mastra packages.
Phase 2: Organization compromise and mass publish (June 17)
At 01:01 UTC on June 17, the attacker published [email protected], identical to the bait release except for the addition of setup.cjs and its postinstall hook. Eleven minutes later, using compromised @mastra organization credentials, they began republishing @mastra packages with "easy-day-js": "^1.11.21" added as a production dependency. Because the caret range ^1.11.21 resolves to the latest matching version at install time, every fresh npm install pulled the malicious 1.11.22. Thirteen packages went out in 36 minutes:
| Time (UTC) | Package |
|---|---|
| 01:01 | [email protected] (malicious dropper) |
| 01:12 | @mastra/[email protected] |
| 01:15 | @mastra/[email protected] |
| 01:16 | @mastra/[email protected] |
| 01:17 | @mastra/[email protected] |
| 01:19 | @mastra/[email protected] |
| 01:25 | @mastra/[email protected] |
| 01:25 | @mastra/[email protected] |
| 01:26 | @mastra/[email protected] |
| 01:29 | @mastra/[email protected] |
| 01:30 | @mastra/[email protected] |
| 01:30 | @mastra/[email protected] |
| 01:41 | @mastra/[email protected] |
| 01:48 | @mastra/[email protected] |
The Dropper Disables Trust, Beacons, Runs, and Erases Itself
When npm installs any infected @mastra package, it resolves easy-day-js to 1.11.22 and runs its postinstall hook:
"postinstall": "node setup.cjs --no-warnings"
The --no-warnings flag suppresses the Node.js deprecation and experimental notices that might otherwise catch a developer's eye. The setup.cjs file is 4,572 bytes and heavily obfuscated using a custom string-encoding scheme: a shuffled-alphabet Base64 variant backed by a 40-element string array that must be rotated 34 positions before the integrity check passes. Stripped of the obfuscation, the logic is compact and deliberate:
- It sets
NODE_TLS_REJECT_UNAUTHORIZED='0', disabling TLS certificate validation so the attacker can serve the next stage over a self-signed certificate on a raw IP. - It writes the install path and an XOR-encoded package marker into
.pkg_historyand.pkg_logsin the system temp directory, a beacon recording where it landed. - It fetches the second stage from
https://23.254.164.92:8000/update/49890878and writes it to a random-named.jsfile in the temp directory. - It spawns that file with
node, passing23.254.164.123:443as an argument, usingdetached: true,stdio: 'ignore', and.unref()so the process outlives the install and produces no output. - It deletes
setup.cjswithfs.rmSync(__filename, { force: true }), removing the first-stage evidence from disk.
What the Second Stage Likely Targets
The second-stage payload is not embedded in the tarball. It is pulled at runtime from attacker infrastructure, so static analysis of the package never sees it. Based on the install context and the infrastructure pattern (the same /24 network and conventional HTTPS port 443 for the beacon), the payload almost certainly harvests environment variables and exfiltrates them to 23.254.164.123:443.
In a Mastra environment, those variables are the crown jewels: LLM keys such as ANTHROPIC_API_KEY and OPENAI_API_KEY, cloud credentials such as AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, and version-control tokens such as GITHUB_TOKEN and NPM_TOKEN. A stolen NPM_TOKEN is how a single compromise becomes the next one.
Indicators of Compromise
Treat any environment that ran npm install for an affected package between 01:01 UTC and the time the versions were pulled as potentially exposed. Hunt for the following.
| Category | Indicator |
|---|---|
| Dependency | easy-day-js at any version in a lockfile or node_modules, especially 1.11.22 and 1.11.21 |
| Packages | The 13 @mastra/* versions listed above in any dependency tree |
| Network (download) | Connections to 23.254.164.92:8000, path /update/49890878 |
| Network (beacon) | Connections to 23.254.164.123:443 |
| Filesystem | .pkg_history and .pkg_logs in the system temp directory; random-named .js files in temp |
| Process | A detached node process launched from a temp-directory script during or just after npm install |
| Manifest | A postinstall hook running node setup.cjs --no-warnings |
| Publisher | npm account sergey2016 as the publisher of easy-day-js |
Immediate Response: The First-Hour Runbook
The dropper runs at install time and the second stage runs detached, so the priority is to assume credential exposure and rotate, not just to remove the package.
- Pin away from the malicious versions. Remove
easy-day-jsentirely and pin affected@mastrapackages to known-good releases published before 01:01 UTC on June 17, 2026. Reinstall from a clean lockfile. - Find every instance. Run
npm ls easy-day-jsand audit lockfiles across repos and CI. The dependency was transitive through @mastra, so it will not appear in your top-levelpackage.json. - Rotate exposed secrets. Assume any credential present in an environment that ran the install is compromised. Rotate LLM API keys, cloud tokens, database credentials,
GITHUB_TOKEN, andNPM_TOKEN. - Block the infrastructure. Block outbound traffic to
23.254.164.92and23.254.164.123and alert on any historical connections. - Check for execution. Search process and network telemetry for the detached
nodeprocess and the C2 callouts. Presence of the package and proof that the dropper ran are different questions. - Inspect CI runners. Ephemeral build agents that ran a fresh install are high priority, because their tokens are often broadly scoped and rarely rotated.
Finding the Package Is Not the Same as Knowing You Were Hit
A dependency scanner tells you easy-day-js is in your tree. It cannot tell you whether the postinstall hook executed, whether the second stage was fetched, or whether your secrets left the building. For an install-time dropper, that gap is the entire incident. Severity without execution context is noise, and "the package is present" is a starting point, not an answer.
That gap between presence and execution is where Kodem operates.
- Kodem's SCA surfaces every copy of
easy-day-jsand every affected@mastraversion across direct and transitive dependency trees, so inventory takes minutes rather than a day of grepping lockfiles. - Runtime Intelligence, Kodem's patented foundational layer, confirms what actually executed: whether the install ran, whether the dropper spawned a process, and whether outbound connections to the C2 infrastructure occurred. That is the difference between "we have the package" and "we were hit."
- Kodem's Application Detection and Response layer catches the behavior this attack depends on: an unexpected subprocess spawned during install and a callout to fresh infrastructure, detected at the moment it happens, without waiting for a signature.
- Kai folds that evidence into a prioritized, ready-to-action response, so the team spends the first hour rotating the right credentials instead of guessing which environments were exposed.
Hardening Against the Next Postinstall Dropper
Install-time execution is the recurring pattern in npm supply chain attacks. Shrinking its blast radius is a configuration problem you can solve before the next one lands.
- Disable install scripts by default in CI with
npm install --ignore-scripts, and allowlist the few packages that genuinely need them. - Adopt an install cooldown so brand-new package versions cannot be pulled into builds within hours of publication.
- Scope CI and npm tokens tightly and rotate them on a schedule, so a single harvested token does not unlock the whole pipeline.
- Pin dependencies with a committed lockfile and review lockfile diffs, where a surprise new transitive dependency like
easy-day-jswould have been visible. - Maintain a current SBOM so a newly disclosed package can be located across every service in minutes.
- Monitor runtime behavior on developer machines and build agents for unexpected subprocess execution and outbound connections to new infrastructure.
What This Signals for AI Framework Supply Chains
AI agent frameworks have become high-value supply chain targets for a simple reason: they live next to the most valuable secrets in a modern stack. The environments that run Mastra, LangChain, and similar tooling hold LLM keys, cloud credentials, and database access, and they run installs constantly as teams iterate on agents.
This campaign also shows how little time defenders get. The decoy was seeded a day in advance, and the weaponized publish window was 36 minutes. Detection that depends on a CVE being assigned, an advisory being written, and a scanner rule being updated is measured in days. The malicious behavior, an install-time process spawning a child and calling out to fresh infrastructure, is observable the moment it happens. Expect more compromises of AI framework dependency trees, and expect the useful question to keep shifting from "is the package present" to "did it execute here."
Frequently Asked Questions
- What happened in the Mastra npm compromise? On June 17, 2026, an attacker with access to the
@mastranpm organization republished 13 packages, each addingeasy-day-js, a typosquat ofdayjs, as a production dependency. That package ran apostinstalldropper that fetched and executed a second-stage payload, then deleted itself. - Which packages are affected? Thirteen
@mastra/*packages including@mastra/[email protected],@mastra/[email protected],@mastra/[email protected],@mastra/[email protected], and@mastra/[email protected], plus the malicious[email protected]. The full list with versions and timestamps is in the timeline above. - How do I know if I am affected? Run
npm ls easy-day-jsand check whether any affected@mastraversion is in your lockfiles ornode_modules. Then check network telemetry for connections to23.254.164.92or23.254.164.123, and process telemetry for a detachednodeprocess launched from the temp directory. - What does the malware steal? The second stage was not retrieved during static analysis, but the install context and infrastructure strongly indicate it harvests environment variables, including LLM API keys, cloud credentials, and VCS tokens, and exfiltrates them to
23.254.164.123:443. - I removed the package. Am I safe? Removing the package stops future installs but does not undo a dropper that already ran. If any affected version was installed, assume the secrets in that environment were exposed and rotate them.
- Why does a dependency scan not settle this? A scan confirms the package is present. It cannot confirm the
postinstallhook executed or that data left the environment. That requires runtime evidence of process execution and network activity, which is the question that actually determines your exposure. - How can I prevent this class of attack? Disable install scripts in CI by default, adopt a publish cooldown for new versions, scope and rotate tokens, review lockfile diffs, and monitor build agents for unexpected subprocess and network behavior.
The Bottom Line
The Mastra compromise is not exotic. A convincing typosquat, a compromised publishing account, a caret version range, and a postinstall hook were enough to turn a routine install into credential theft across developer machines and CI. The fix is straightforward: remove easy-day-js, pin to clean versions, and rotate exposed secrets.
The harder problem is knowing where the dropper actually ran and what it touched. That is a runtime question, not a scanner question, and it is the part Kodem connects from code to runtime. SCA finds every affected package in the dependency graph, Runtime Intelligence proves whether the malicious code executed, and Kai turns that into a prioritized response while the tokens are still being rotated.
References
- StepSecurity. June 17, 2026. @mastra npm Packages Compromised. stepsecurity.io.
- Mastra. Issue #18045: compromised package versions. github.com/mastra-ai/mastra.
- Kodem Security. From Reachability to Reality: Proving Vulnerable Code Was Executed and Exploited in Production. Kodem Security.
- Kodem Security. Tanstack and OpenAI Supply Chain Attack: Mini Shai-Hulud IOCs and First-Hour Response Runbook. Kodem Security.
- Kodem Security. Know which packages are actually exploitable in your environment. Kodem Security.
- Kodem Security. Stop attacks at the first malicious action. Kodem Security.
Related blogs

CVE-2026-9277 shell-quote Command Injection
CVE-2026-9277 is a shell-quote command injection flaw in npm versions 1.1.0 through 1.8.3. See how the quote() bypass works, what to hunt, and the 1.8.4 fix.
9
A Primer on Runtime Intelligence
See how Kodem's cutting-edge sensor technology revolutionizes application monitoring at the kernel level.
Platform Overview Video
Watch our short platform overview video to see how Kodem discovers real security risks in your code at runtime.
The State of the Application Security Workflow
This report aims to equip readers with actionable insights that can help future-proof their security programs. Kodem, the publisher of this report, purpose built a platform that bridges these gaps by unifying shift-left strategies with runtime monitoring and protection.
.avif)
Get real-time insights across the full stack…code, containers, OS, and memory
Watch how Kodem’s runtime security platform detects and blocks attacks before they cause damage. No guesswork. Just precise, automated protection.


.avif)