安全玻璃盒供应链安全威胁情报中心检测发现,一名攻击者接管了一名 Mastra 维护者的账号,并利用该账号对项目进行了大规模篡改。在短短 27 分钟内,他们重新发布了整个 @mastra 目录下的所有包。他们并没有动 Mastra 自身的代码,而是在每个包中都修改了一行代码,添加了一个指向名为 easy-day-js 的伪造组件的隐藏链接——该组件是针对广泛使用的工具 dayjs 的仿冒品。

Mastra 是一个开源工具包,软件开发者利用它来构建 AI 应用和智能体(agents)。它出自 Gatsby 背后的团队之手,并被广泛采用:该项目的组件每月被构建在其之上的团队下载超过 2800 万次。像大多数现代软件一样,Mastra 以一组小型、可重用的构建块形式分发,其他程序会自动拉取这些构建块。正是这种广泛的影响力,使得一个账号被盗变得如此危险。
easy-day-js 是一种“拼写劫持”(typosquat)攻击。它从描述到捆绑的 dayjs.min.js 文件都在模仿 dayjs,但增加了一个运行“投毒器”(dropper)的安装后钩子(postinstall hook)。安装时,该投毒器会禁用 TLS 证书验证,从一个原生 IP 地址获取第二阶段恶意负载(payload),将其写入临时目录,并作为分离且隐藏的子进程运行,最后自我删除。

这次事件有三个显著特点:
整个组织账号瞬间沦陷:这并非针对单个包,而是在不到半小时内对 116 个包进行了脚本化的扫荡,大致按下载量排序。这表明是一个拥有整个范围(scope)发布权限的账号被劫持,而非单一的恶意发布。
载体包本身是“干净”的,负载隐藏在下一层:每个 Mastra 包本身都是未经修改的库,仅包含一行被投毒的依赖项。那些仅检查指定包自身代码的扫描工具将无法发现任何异常。恶意行为存在于 easy-day-js 中,而在大多数 Mastra 包中,该依赖项甚至从未被实际导入调用。
预先部署的诱饵依赖:easy-day-js@1.11.21 在一天前就已发布,且没有安装钩子,是一个干净的诱饵。而被武器化的 1.11.22 版本于 UTC 时间 01:01 上线,仅比 Mastra 扫荡开始早了 11 分钟。
以下所有版本均为恶意版本,发布于2026年6月17日。请固定到每个版本的最后已验证来源发布的版本,并将这些特定版本视为已被入侵。
Package | Malicious version | Published (UTC) | Downloads/month |
@mastra/schema-compat | 1.2.12 | 1:12 | 5,279,923 |
@mastra/core | 1.42.1 | 1:15 | 4,013,267 |
mastra | 1.13.1 | 1:20 | 2,139,510 |
@mastra/memory | 1.20.4 | 1:16 | 2,057,689 |
@mastra/server | 2.1.1 | 1:17 | 1,864,647 |
@mastra/deployer | 1.42.1 | 1:19 | 1,858,620 |
@mastra/observability | 1.14.2 | 1:18 | 1,695,048 |
@mastra/loggers | 1.1.3 | 1:18 | 1,672,903 |
@mastra/pg | 1.13.1 | 1:25 | 1,361,195 |
@mastra/mcp | 1.10.1 | 1:25 | 1,203,924 |
@mastra/ai-sdk | 1.4.6 | 1:27 | 1,069,650 |
@mastra/libsql | 1.13.1 | 1:26 | 977,312 |
@mastra/langfuse | 1.3.6 | 1:29 | 617,580 |
@mastra/evals | 1.3.1 | 1:29 | 476,879 |
@mastra/rag | 2.2.2 | 1:30 | 307,033 |
@mastra/datadog | 1.2.5 | 1:30 | 253,586 |
@mastra/duckdb | 1.4.3 | 1:32 | 222,862 |
@mastra/braintrust | 1.1.4 | 1:33 | 187,050 |
@mastra/dynamodb | 1.0.9 | 1:31 | 160,266 |
@mastra/hono | 1.4.26 | 1:32 | 152,792 |
@mastra/otel-bridge | 1.2.3 | 1:33 | 132,788 |
@mastra/editor | 0.11.3 | 1:34 | 128,885 |
@mastra/langsmith | 1.2.4 | 1:34 | 120,459 |
@mastra/mcp-docs-server | 1.1.47 | 1:37 | 97,609 |
@mastra/mongodb | 1.9.3 | 1:35 | 92,100 |
@mastra/posthog | 1.0.29 | 1:36 | 90,917 |
@mastra/fastembed | 1.1.3 | 1:39 | 77,220 |
@mastra/s3 | 0.5.3 | 1:38 | 64,299 |
@mastra/sentry | 1.1.4 | 1:35 | 63,793 |
@mastra/fastify | 1.3.31 | 1:39 | 61,020 |
@mastra/auth | 1.0.3 | 1:38 | 59,979 |
@mastra/inngest | 1.5.2 | 1:39 | 51,427 |
@mastra/acp | 0.2.2 | 1:55 | not separately reported |
@mastra/agent-browser | 0.3.2 | 1:42 | not separately reported |
@mastra/agent-builder | 1.0.42 | 1:59 | not separately reported |
@mastra/agentcore | 0.2.2 | 2:23 | not separately reported |
@mastra/agentfs | 0.1.1 | 2:17 | not separately reported |
@mastra/arize | 1.2.3 | 1:44 | not separately reported |
@mastra/arthur | 0.3.3 | 2:22 | not separately reported |
@mastra/astra | 1.0.2 | 2:06 | not separately reported |
@mastra/auth-auth0 | 1.0.2 | 1:54 | not separately reported |
@mastra/auth-better-auth | 1.0.4 | 1:45 | not separately reported |
@mastra/auth-clerk | 1.0.3 | 1:46 | not separately reported |
@mastra/auth-cloud | 1.1.4 | 2:08 | not separately reported |
@mastra/auth-firebase | 1.0.1 | 2:20 | not separately reported |
@mastra/auth-okta | 0.0.5 | 2:18 | not separately reported |
@mastra/auth-studio | 1.2.4 | 2:16 | not separately reported |
@mastra/auth-supabase | 1.0.2 | 1:47 | not separately reported |
@mastra/auth-workos | 1.5.3 | 1:55 | not separately reported |
@mastra/azure | 0.2.3 | 2:18 | not separately reported |
@mastra/blaxel | 0.4.2 | 1:57 | not separately reported |
@mastra/brightdata | 0.2.2 | 2:19 | not separately reported |
@mastra/browser-viewer | 0.1.3 | 2:15 | not separately reported |
@mastra/chroma | 1.0.2 | 1:45 | not separately reported |
@mastra/claude | 1.0.3 | 2:02 | not separately reported |
@mastra/clickhouse | 1.10.1 | 1:37 | not separately reported |
@mastra/client-js | 1.24.1 | 1:26 | not separately reported |
@mastra/cloudflare | 1.4.2 | 1:55 | not separately reported |
@mastra/cloudflare-d1 | 1.0.7 | 1:50 | not separately reported |
@mastra/codemod | 1.0.4 | 2:23 | not separately reported |
@mastra/convex | 1.2.2 | 1:46 | not separately reported |
@mastra/couchbase | 1.0.4 | 1:58 | not separately reported |
@mastra/cursor | 0.2.1 | 2:04 | not separately reported |
@mastra/daytona | 0.4.2 | 1:41 | not separately reported |
@mastra/deployer-cloud | 1.42.1 | 2:05 | not separately reported |
@mastra/deployer-cloudflare | 1.1.44 | 1:47 | not separately reported |
@mastra/deployer-netlify | 1.1.20 | 2:02 | not separately reported |
@mastra/deployer-vercel | 1.1.38 | 1:41 | not separately reported |
@mastra/docker | 0.3.1 | 1:53 | not separately reported |
@mastra/dsql | 1.0.3 | 1:57 | not separately reported |
@mastra/e2b | 0.3.4 | 1:44 | not separately reported |
@mastra/elasticsearch | 1.2.1 | 2:20 | not separately reported |
@mastra/express | 1.3.31 | 1:31 | not separately reported |
@mastra/files-sdk | 0.2.1 | 2:06 | not separately reported |
@mastra/gcs | 0.2.3 | 1:48 | not separately reported |
@mastra/github-signals | 0.1.2 | 2:07 | not separately reported |
@mastra/google-cloud-pubsub | 1.0.6 | 2:03 | not separately reported |
@mastra/google-drive | 0.1.1 | 2:21 | not separately reported |
@mastra/koa | 1.5.14 | 2:00 | not separately reported |
@mastra/laminar | 1.2.3 | 2:09 | not separately reported |
@mastra/lance | 1.0.7 | 2:04 | not separately reported |
@mastra/longmemeval | 1.0.50 | 1:54 | not separately reported |
@mastra/mcp-registry-registry | 1.0.2 | 2:00 | not separately reported |
@mastra/mssql | 1.3.2 | 1:56 | not separately reported |
@mastra/mysql | 0.1.1 | 2:21 | not separately reported |
@mastra/nestjs | 0.1.15 | 1:51 | not separately reported |
@mastra/openai | 1.0.2 | 2:05 | not separately reported |
@mastra/opencode | 0.0.47 | 2:17 | not separately reported |
@mastra/opensearch | 1.0.3 | 2:04 | not separately reported |
@mastra/otel-exporter | 1.2.3 | 1:28 | not separately reported |
@mastra/perplexity | 0.1.1 | 2:24 | not separately reported |
@mastra/pinecone | 1.0.2 | 1:52 | not separately reported |
@mastra/playground-ui | 33.0.1 | 1:49 | not separately reported |
@mastra/qdrant | 1.0.3 | 1:46 | not separately reported |
@mastra/react | 1.0.1 | 1:42 | not separately reported |
@mastra/redis | 1.1.3 | 1:48 | not separately reported |
@mastra/redis-streams | 0.0.4 | 2:03 | not separately reported |
@mastra/s3vectors | 1.0.7 | 1:50 | not separately reported |
@mastra/slack | 1.3.1 | 2:19 | not separately reported |
@mastra/spanner | 1.1.2 | 2:22 | not separately reported |
@mastra/stagehand | 0.2.5 | 1:40 | not separately reported |
@mastra/tavily | 1.0.3 | 1:45 | not separately reported |
@mastra/temporal | 0.1.14 | 1:53 | not separately reported |
@mastra/turbopuffer | 1.0.3 | 1:52 | not separately reported |
@mastra/twilio | 1.0.2 | 2:16 | not separately reported |
@mastra/upstash | 1.1.3 | 1:43 | not separately reported |
@mastra/vectorize | 1.0.3 | 1:58 | not separately reported |
@mastra/voice-aws-nova-sonic | 0.1.4 | 2:01 | not separately reported |
@mastra/voice-azure | 0.11.2 | 2:23 | not separately reported |
@mastra/voice-deepgram | 0.12.2 | 1:53 | not separately reported |
@mastra/voice-elevenlabs | 0.12.2 | 1:51 | not separately reported |
@mastra/voice-google | 0.12.3 | 1:51 | not separately reported |
@mastra/voice-google-gemini-live | 0.12.2 | 1:43 | not separately reported |
@mastra/voice-openai | 0.12.3 | 1:42 | not separately reported |
@mastra/voice-openai-realtime | 0.12.6 | 1:40 | not separately reported |
create-mastra | 1.13.1 | 1:56 | not separately reported |
Package | Version | Role |
easy-day-js | 1.11.22 | Weaponized, postinstall dropper, published 2026-06-17 01:01 UTC |
时间 (UTC) | 事件 |
2026-06-16 07:05 | 发布 easy-day-js@1.11.21,一个没有安装钩子(install hook)的干净诱饵 |
2026-06-17 01:01 | 发布 easy-day-js@1.11.22,携带安装后投毒器(postinstall dropper) |
2026-06-17 01:12 | 第一个 Mastra 包被重新发布 (@mastra/schema-compat) |
2026-06-17 01:12 - 01:39 | 32 个 Mastra 包由 ehindero 重新发布,且无Attestations信息(no provenance) |
除上表列出的所有 32 个 Mastra 版本外,还包括:
指标 | 备注 |
easy-day-js@1.11.22 | 武器化的投毒器 (Dropper) |
easy-day-js@1.11.21 | 干净的诱饵,但仍由攻击者控制,应予以封禁 |
发布者 ehindero / ehindero2016@tutamail.com | 用于所有恶意发布的账号 |
2026-06-17 发布且无 SLSA 溯源的任何 @mastra/* 或 mastra 版本 | 在 CI 流程之外进行的手动发布 |
指标 | 备注 |
https://23.254.164.92:8000/update/49890878 | 第二阶段恶意负载 (Payload) 的 URL |
23.254.164.123:443 | 位于同一 /24 网段的次要端点 |
指标 | 备注 |
~/.pkg_history | 包含安装路径的标记文件 |
~/.pkg_logs | 由钩子 (hook) 投放的标记文件 |
主目录下随机命名的 <24位十六进制>.js 文件 | 获取到的第二阶段负载 |
npm install 期间运行 node setup.cjs | 投毒器正在运行 |
安装脚本设置了 | 禁用了 TLS 证书验证 |
安装期间生成了分离的 node 子进程 | 恶意负载正在后台运行 |
特征码 | 备注 |
"postinstall": "node setup.cjs --no-warnings" | 存在于 easy-day-js@1.11.22 中 |
process.env.NODE_TLS_REJECT_UNAUTHORIZED='0' | 存在于 setup.cjs 中 |
Buffer.from(... ); ... spawn(process.execPath, ...).unref() | 分离式启动恶意负载的代码 |
fs.rmSync(__filename, { force: true }) | finally 代码块中的自删除操作 |
检查您的依赖树中是否存在受影响的软件包或投毒器:
# 检查是否存在 easy-day-js
npm ls easy-day-js
# 在 lock 文件中查找 Mastra 相关包或 easy-day-js
grep -REn "@mastra/|"mastra"|easy-day-js" package-lock.json yarn.lock pnpm-lock.yaml 2>/dev/null
在主机和 CI 运行器(CI Runners)上寻找留下的痕迹(Artifacts):
# 检查标记文件是否存在
ls -la ~/.pkg_history ~/.pkg_logs 2>/dev/null
# 查找 2026-06-17 之后在主目录下生成的随机 .js 文件
find "$HOME" -maxdepth 1 -type f -name '*.js' -newermt '2026-06-17' 2>/dev/null
预防措施:
请视该主机为已失陷(Compromised)。 投毒器在进程内禁用了 TLS 验证,并启动了一个内容在运行时动态获取的脱离父进程的子进程。因此,安装钩子(Install Hook)所表现出的行为并不是攻击的全部。
更新时间:2026-06-18
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight All Rights Reserved.
Powered By 61893.com 闽ICP备11008920号
闽公网安备35020302035593号