深海军蓝背景上的一幅生成的抽象插画:以剖面视角呈现的一叠五个薄薄的青色内存托盘,每个托盘里装着一排排小灰块,其中一个小琥珀色立方体卡在第三个与第四个托盘之间;从那个立方体出发,一条由粒子组成的细琥珀色丝线划出一道弧线,穿过深色虚空,伸向三个排成三角形的小红橙色节点。托盘后方,暗淡的灰色标签挂在由细环系着的钥匙圈上。画面中没有文字、人物或组织标志。OrcaRouter 标志合成在右下角。
AI Safety Incidents

sckit:MemTensor 的 AI 记忆包被植入后门,用于窃取智能体凭据和提示词

作者

Rowan Sterling

发布日期

最新模型 · 20查看全部模型 →
基准测试:Artificial Analysis · 每日更新
返回全部文章

MemTensor 的四个版本2026年9月23日发布,均携带相同的去符号 Go 植入程序,而且每个版本在上线期间都是其所在注册表上的最新版本。npm 的 @memtensor/memos-cloud-openclaw-plugin 发布了 0.1.21,时间为 02:23 UTC;0.1.23 于 03:49 发布,0.1.25 于 04:36 发布;PyPI 的 MemoryOS 发布了 2.0.34,时间为 05:25。四个版本都附带 sckit,它会在 OpenClaw 代理网关启动时启动,在每次记忆召回时再次启动——此时用户提示文本会通过环境变量传入——并且在 Python 包中,只要直接导入 memos 模块就会启动。随后,它会扫描主目录,查找 npm、PyPI、GitHub、GitLab、AWS、Vault 和 SSH 的密钥,并将找到的内容发送到 skyleen[.]fr 下的服务器。Socket、StepSecurity、SafeDep 和 Aikido 当天各自独立记录了这起入侵事件,且均未报告有证据表明该植入程序曾在真实主机上运行。Orca AI Incident Archive 完整收录了此条目,并与 它记录的所有其他供应链事件一并收录;每条记录都带有自己的置信度等级和危害状态。

四个版本,以及夹在它们中间的一份公开缺陷报告

MemOS 是 MemTensor 面向 LLM 智能体的开源记忆框架,而该 npm 包是连接器,使 OpenClaw 智能体运行时能够读写托管记忆服务;StepSecurity 指出,同一个包还声明了面向 Clawdbot 和 Moltbot 运行时的集成点。Socket 统计该仓库约有11,500 个星标和1,100 个分叉,这是其发布时的数据。正是这一地位使此次入侵事件引发了四项独立调查:正如 StepSecurity 所说,这“将插件置于一个经常处理用户输入、并可能继承有价值凭据的进程之中”。受影响的人群是安装了这两个包中任意一个的人——包括在自己机器上工作的开发者,以及仅运行测试套件的 CI 运行器和容器。

npm 序列是记录中最清晰的部分,因为注册表时间戳是公开的,而且有多家公司独立捕获了它们。Socket 的报道和 SafeDep 的时间线在每一分钟上都一致:0.1.21 于 02:23:04,0.1.22 于 03:45:44,0.1.23 于 03:49:20,0.1.24 于 04:33:30,以及 0.1.25 于 04:36:58。版本 0.1.22 和 0.1.24 是干净的——Socket 表示,除版本字符串外,它们与 0.1.20 一致——并且有效载荷在它们各自之后的三分半钟返回。

体积激增就是线索。Socket 测得 0.1.20 解包后约为 272 KB,而 0.1.21 为 43.6 MB,因为恶意版本捆绑了六个静态链接的平台二进制文件,每个约 7.4 MB。PyPI 也显示出同样的模式:2.0.34 的 wheel 为 19,201,772 字节,而 951,210(对应 2.0.33,据 Socket 称)。

UTC 04:17——在干净的 0.1.24 发布前十六分钟、在载荷以 0.1.25 返回前十九分钟——一位名为 omeridel 的 GitHub 用户在插件仓库上打开了议题 #173,标题为“恶意版本 0.1.21 和 0.1.23 已发布到 npm——发布令牌似乎已泄露”。该议题指出,0.1.23 当时是最新标签,这两个版本均未匹配仓库中的任何提交或标签,而最近一次合法提交的日期为 8 月 14 日。截至 2026 年 10 月 26 日,该议题仍处于打开状态,维护者未发表任何评论。

A self-built HTML card headed 'Supply chain, 23 September 2026, all times UTC', titled 'Four and a half hours on npm and PyPI', subtitled 'Each malicious release was the registry's newest version while it was live'. Nine rows, each with a time, an event, a detail and a status chip: 00:48 attacker branch first pushed, pipeline; 02:23 npm 0.1.21 published, 43.6 MB unpacked up from 272 KB, malicious; 03:17 MemOS commit b52958f, six sckit binaries and a CI token stealer, malicious; 03:45 npm 0.1.22 published, matches 0.1.20 apart from version strings, clean; 03:49 npm 0.1.23 published, payload restored three minutes later, malicious; 04:17 GitHub issue 173 filed, disclosure; 04:33 npm 0.1.24 published, clean again and the latest tag for three minutes; 04:36 npm 0.1.25 published, payload back and this one takes the latest tag, malicious; 05:25 PyPI MemoryOS 2.0.34, 19.2 MB wheel against 951 KB in 2.0.33, malicious. A footer reads 'Timestamps from Socket and SafeDep, which agree to the minute. Sizes from Socket.' The OrcaRouter logo is composited in the bottom-right corner.

sckit 在包加载后会做什么

这两个包都没有使用安装钩子,因此关于 --ignore-scripts 的常见建议并不适用。StepSecurity 对 npm 变体的分析描述了一个新文件 lib/sckit.js,该文件导出一个启动器,插件现有的启动和记忆召回代码会导入并调用它。启动时,它会生成一个分离的 .sckit/<os>-<arch>/sckit 进程,使用 stage0 --config64 以及父进程的完整环境;在召回时,它也会这样做,并通过名为 SCKIT_EVENT_TEXT 的环境变量传递剥离后的用户提示。Socket 直白地说明了后果:因此,该二进制文件会在每次召回时再次运行。

PyPI 变体更短,而且实际上更难避开。Socket 发现,memos/log.py 在配置日志记录时会调用 memos/_stage0.py 中的一个触发函数,有 149 个模块在模块级别调用该记录器,因此单纯导入 memos 模块就足以让有效载荷在每个进程中启动一次。StepSecurity 对同一软件包的分析纯粹是静态的——它没有安装、导入、构建或执行该软件包。

收集范围是整个主目录。SafeDep 将清单根目录列为 $HOME,并将目标文件列为 .npmrc、.pypirc、.git-credentials、.netrc、id_rsa、id_ecdsa、id_ed25519、.vault-token、msal_token_cache、access_tokens.json 和 access_tokens.db,还包括名称中包含 token、secret、password、API key 或 database URL 的环境变量,以及 GitHub、GitLab、npm、PyPI、Hugging Face、Slack、Stripe、AWS 和 SendGrid 的可识别令牌格式。针对这两个包的 OSV 记录,MAL-2026-16476(针对 npm)和 MAL-2026-16475(针对 PyPI)描述了相同的文件列表,并补充说命令与控制协议使用 CBOR、X25519 密钥交换和 XChaCha20-Poly1305,采用签名租约和在运行时交付的模块——因此从未观察到模块的内容,只观察到获取这些模块的加载器。

有两个细节决定了防御者仍能恢复什么。该二进制文件带有名为 scheduleSelfDelete 和 deleteExecutable 的自删除例程,根据 OSV 记录,这就是为什么指导方针是搜寻进程和网络痕迹而非文件。0.1.25 还添加了 lib/tls-trust.js,根据 StepSecurity,它会在最小化 Linux 系统上将 SSL_CERT_FILE 设置为一个捆绑的包含 145 个证书的证书颁发机构文件——这一修复旨在使其自身流量在缺少系统信任存储的容器中正常工作。

A generated abstract illustration on a dark navy field: at left, a dim cyan isometric tree of folders, several leaves carrying small grey key and badge silhouettes; from those keys a cluster of amber threads lifts away, braids into one bright cord and runs right through a narrow vertical cyan gateway frame that carries an amber keyhole, toward three small red-orange receivers with faint pulse rings on the far right. No text, people or organisation logos appear. The OrcaRouter logo is composited in the bottom-right corner.

发布流水线曾是入口。

SafeDep 的重构是对初始访问最详细的叙述,并且它指向 GitHub Actions,而不是被盗的注册表密码。在 UTC 00:48 至 02:03 期间,一个以 Memtensor-AI 身份运行的 GitHub 账户创建、推送并删除了一个名为 sc/release-0.1.21-20260922-cloud 的分支,共五次。提交 9b97ec6 修改了工作流脚本 .github/scripts/validate-release-confirmation.mjs,使其将 BASH_ENV 值追加到 $GITHUB_ENV,这导致后续非交互式 shell 步骤在执行自己的命令之前,会先加载攻击者提供的 sckit-publish-bridge.sh。该桥接脚本会检查包名和发布步骤的 150 秒超时,使用 NPM_TOKEN 或 NODE_AUTH_TOKEN 调用令牌收集器,删除自身并以退出码 1 退出——因此发布在令牌已被取走后失败了。首个恶意 npm 发布版本出现在最后一次分支推送后二十分钟。

PyPI 路径对另一条流水线使用了同样的手法。SafeDep 报告称,标签 v2.0.34指向了不在 main 上的未签名提交,并且提交 b52958f(作者署名为“MemTensor CI Review”)添加了六个二进制文件、一个 Python 加载器,以及一个名为 sckit_poetry_build的自定义构建后端。该后端写入了一个 BASH_ENV,它指向 _pypi_bridge.sh,并将其写入 $GITHUB_ENV;该桥接程序只在 twine 上传包装器内部起作用,它从 skyleen[.]fr 主机获取了一个签名索引,使用 Ed25519 实现验证了一个 emitter,打印了一行标记,取消设置了上传密码,然后退出,没有上传任何内容。大约两小时后,提交 41bf5c7以“chore: allow native PyPI upload [skip ci]”为提交信息移除了该调用,标签在十秒内被删除并重新创建,随后 62 秒后进行了 PyPI 上传。SafeDep 将第一个提交解读为一次捕获令牌的运行,将第二个解读为让 MemTensor 自己的工作流使用项目的真实令牌构建并发布恶意软件包的那次运行。

并非所有说法在这一点上都吻合。Socket 观察到,这些 npm 发布版本与早先的合法版本来自同一个 npm 账户,并且缺少 gitHead;它将此视为这些版本并非由该项目 CI 生成的迹象,并表示无法确认攻击者是如何获得发布访问权限的。SC Media 在 9 月 24 日报道 Socket 的调查结果时,也作出了同样的推断,认为账户遭到入侵。两种说法都认为发布凭据是从发布流水线中获取的,但在 npm 制品本身是如何产生的一点上存在分歧;没有人公布工作流日志,因为 GitHub 的 Actions API 显示 9 月 7 日之后没有运行记录,而 SafeDep 推断这些记录已被删除。在两种说法中,Memtensor-AI 账户最初是如何获得推送权限的仍不得而知;SafeDep 称账户令牌被盗的可能性很大,但尚未证实。

已确立、推断的和缺失的

该记录的置信等级为 A,且没有争议;这一点值得精确说明,因为这种确定性针对的是已发布的内容,而不是它实际做了什么。

• 已确认:由 Socket、StepSecurity 和 SafeDep 通过静态分析重建的四个工件的相关内容;npm 发布时间以及 0.1.25 上的 latest 标签;两个生态系统中的体积跃升;两个仓库中的提交、标签和分支历史;skyleen[.]fr 基础设施以及活动标识符 cloud-openclaw-semi-nuclear 和 memos-semi-nuclear;以及该载荷的配置,据 Socket 和 SafeDep 称,该配置将于 2026 年 10 月 22–23 日到期。

• 推断:该工具是在语言模型的帮助下编写的,SafeDep 直接说明了这一点并将其称为推断;以及被盗的发布令牌原本打算被重复使用,配置中的通道字符串——“exact-ref-one-use-NPM_TOKEN”——支持这一点,但并不能证明。

• 尚未确定:攻击者是谁;sckit 的任何副本是否曾在沙箱之外执行过;是否有任何凭据离开了主机;输入 OpenClaw 代理的任何提示词是否到达了攻击者手中;以及是否有任何下游软件包被重新发布。Socket 和 StepSecurity 均以静态方式开展工作,StepSecurity 表示,其分析中未观察到任何进程运行、任何机密传输、任何成功的窃取、任何工作流安装,也未观察到任何进一步的软件包发布。

这一缺口正是档案库将本次事件中的实际危害标记为 false 的原因。暴露是真实且广泛的——任何安装了受影响版本的人都被要求将该主机视为已遭入侵——但就凭据被明确使用或系统被明确访问这一意义上的危害而言,四家调查公司均未记录到。

A self-built HTML card headed 'What the record supports', titled 'Four investigating firms, no confirmed victim', subtitled 'Socket, StepSecurity, SafeDep and Aikido documented the same four artefacts on 23 September 2026'. The left column, headed 'Established by static analysis', lists: four malicious releases, npm 0.1.21, 0.1.23 and 0.1.25 and PyPI MemoryOS 2.0.34; one implant, the same stripped Go binary sckit in all four; the publish window 02:23 to 05:25 UTC with 0.1.25 tagged latest; package growth from 272 KB to 43.6 MB on npm and 951 KB to 19.2 MB for the PyPI wheel; six builds per package for Linux, macOS and Windows on amd64 and arm64; collection scoped to the whole home directory across registry, source-control, cloud, Vault and SSH secrets; exfiltration to servers under skyleen[.]fr; and OSV tracking as MAL-2026-16476 and MAL-2026-16475. The right column, headed 'Not established', lists: the attacker's identity; how Memtensor-AI obtained push access; whether any copy ever executed outside static analysis; whether a stolen secret reached the attacker; whether any prompt text was received; and whether any downstream package was republished. A footer reads 'Archive classification for this record: incident, severity high, confidence A, real harm false.' The OrcaRouter logo is composited in the bottom-right corner.

从未见其传播的蠕虫

这些二进制文件包含的远不止一个窃取程序。SafeDep 列出了名为 recursivePublish、prepareRemoteNode、prepareRemotePython 和 prepareRemoteWorkflow 的函数,此外还有一个在 push 时触发的嵌入式 GitHub Actions 模板,以及将名为 runtime-update.yml 的工作流文件写入植入程序可触及的仓库的能力。Socket 发现了关于编码包清单和安装仓库文件的字符串,并评估认为这些二进制文件可能能够利用窃取的注册表令牌重新发布软件包。

这是一种蠕虫设计,但并不是被观察到实际发挥作用的蠕虫。StepSecurity未发现任何证据表明该逻辑曾被用于传播,云安全联盟(Cloud Security Alliance)9月25日的研究简报认为,该能力仅具有有限的自我传播潜力,而非已确认的蠕虫行为。多家媒体将该事件描述为首个针对AI智能体记忆基础设施的供应链蠕虫;作为对设计的描述,这一说法是合理的,但相关报道并不支持将其作为对实际发生情况的描述。

后来发生了什么变化?

注册表在同一天完成了清理。于2026年10月26日检查时,npm 包的元数据已不再在其版本列表中列出 0.1.21、0.1.23 或 0.1.25,latest 标签指向 0.1.24,该包的最后修改时间为9月23日11:53 UTC。仍附有两个异常的 dist-tag——clean-inverse-0-1-23 指向 0.1.22,clean-inverse-0-1-25 指向 0.1.24——对应着曾短暂打断恶意版本的两个干净版本。在 PyPI 上,MemoryOS 2.0.34 已消失,最新版本是 2.0.33,于2026年9月3日上传;此后七周内 PyPI 上没有进一步发布。

始终未变的是该项目的公开说法。代码仓库未列出任何安全公告,事发当天 04:17 的 GitHub issue 仍处于开放状态且无人回应,而本文所考察的报道中,没有任何一篇引用了 MemTensor 或 OpenClaw 的声明。两个恶意包均未附带来源证明(provenance attestation),SafeDep 指出,这抹去了唯一能表明这些制品是由一次意外提交构建而来的信号。

确实存在的应对是在检测方面:StepSecurity 已将 skyleen[.]fr 命令与控制域名添加到其全球阻止列表,而这两个软件包在 OSV 中被追踪为 MAL-2026-16476 和 MAL-2026-16475。

如果安装了受影响的版本

Socket 的指引最严格也最简单:如果任何列出的版本曾被加载或导入,就将该主机视为已失陷,包括仅运行过测试的 CI runner 和容器。四家厂商一致得出的具体步骤如下:

• 移除该软件包并锁定到干净版本——npm 0.1.20,PyPI 2.0.33。StepSecurity 提醒称,其分析未能确立干净的 PyPI 基线,而 SafeDep 和 SC Media 都将 2.0.33 列为最后一个良好版本。

• 查找进程命令行,因为可执行文件可能会删除自身:sckit stage0 --config64,以及环境变量 SCKIT_EVENT_TEXT。

• 删除状态目录 ~/.openclaw/.cache/runtime 和 ~/.memos/.cache/runtime,并检查仓库中是否存在意外的 runtime-update.yml 工作流或 .sckit/ 目录。

• 在一台干净的机器上,轮换所有能够从主目录和进程环境中访问到的凭据:npm、PyPI、GitHub、GitLab、AWS、Vault、SSH、Hugging Face、Slack、Stripe 和 SendGrid,以及所有 .env 值。注册表和源代码管理令牌优先处理。

• 检查你自己软件包的发布版本,以防有人使用被盗的发布令牌发布了并非你编写的版本。

• 阻止 skyleen[.]fr 及其子域,并读取可追溯至 9 月 23 日的出站日志。

把插件处于活动状态期间经由它传递的任何提示词或粘贴的密钥,都视为已经泄露。这是该事件中与智能体记忆相关的那部分:植入程序无需抓取对话记录,因为每次召回时记录都会被直接交给它。