[tool.maturin]
data = "cook"
2026 年 10 月 21 日 11:39:51 UTC,开源大模型网关 LiteLLM 向 PyPI 推送了 1.107.0 正式版。源码包的 pyproject.toml 里只多出这一行配置。但在随后两小时内,它把所有未锁版本的部署节点变成了凭证收割机。AI 基础设施的信任边界已经从「审查依赖源码」坍塌到了「守护构建凭证」;而这次把发布钥匙交到攻击者手里的,恰恰是开发者日常使用的 AI 编程助手。
12 字节钩子接管解释器,不导包也中招
litellm==1.107.0 在 PyPI 上存活到 13:23 UTC,窗口期约两小时。覆盖 Linux、macOS 与 Windows 的七个 wheel 包全部携带恶意载荷。同时,Docker Hub 与 GHCR 上的 v1.107.0、latest、main-latest、main-stable 四个标签也遭篡改。从 11:46:56 到 14:20 UTC,这些标签统一指向投毒镜像 sha256:1bbcb1443bc962e45f5aad53fe3d2c30600e0379715fb6c664cdd3ac126c339e。未锁死版本的 CI/CD 流水线一旦拉取更新,就会直接把后门迎进生产环境。
恶意代码通过 Maturin 的 data = "cook" 指令塞进 wheel 的 purelib/ 目录。包安装后会在 site-packages 下释放三个文件:12 字节的 cook.pth、22252 字节的 cook.py,以及 25509 字节的 sitecustomize.py。BerriAI/litellm 的公开仓库里从没出现过 cook/ 目录,源码包里也没有对应文件。只看 GitHub 公开提交记录的安全审计,在构建期注入面前形同虚设。
cook.pth 里只有一行 import cook。按照 Python 的 .pth 机制,解释器启动时会自动执行其中以 import 开头的语句。同目录的 sitecustomize.py 也是启动即加载的全局钩子,与 cook.py 里的压缩载荷构成双保险。攻击载荷跳过了业务代码的导入链路,哪怕宿主机从不执行 import litellm,光是运行 pip 或启动 IDE 语言服务器都会立刻触发后门。
图:LiteLLM 1.107.0 恶意包的文件注入与双载荷执行链路。来源:SafeDep(供应链安全分析报告)
16 个采集模块专盯 AI 工具链与网关数据库
第一层载荷 cook.py 内置了 16 个采集模块,把目标机器翻了个底朝天。它首先读取 ~/.ssh/* 私钥、Shell 历史记录,并用 DPAPI 或主密钥解密 Chromium 与 Firefox 保存的密码。接着,它会搜刮 AWS、Azure、GCP、~/.kube/config、Docker、gh、Vault 与 Terraform 的凭据文件。它还会请求 AWS IMDS 元数据接口(先试 IMDSv2 再退回 IMDSv1),并遍历 /proc/<pid>/environ 读取其他进程的环境变量。这套载荷已经按现代云原生工程师的完整工作台完成了清单定制。
最能暴露攻击者意图的是 ai_devtools 与 db_litellm 两个专属模块。ai_devtools 专门搜捕 17 类 AI 开发工具凭证,涵盖 Claude Code、Claude Desktop、Cursor、Windsurf、Copilot、VS Code 的 mcp.json、Gemini CLI、Codex、Continue、Aider、Zed 与 Hugging Face 等;db_litellm 则读取 DATABASE_URL,把网关数据库里的 LiteLLM_CredentialsTable 与 LiteLLM_ProxyModelTable 整表导出。AI 网关天生是企业大模型调用的凭证集线器,攻陷一台 LiteLLM 代理实例,就等于一次性拿走了它背后挂载的全部上游模型 API 密钥。
窃取的数据先用随机 AES-256-CBC 密钥加密,再用内置 RSA-4096 公钥做 OAEP 封装。随后数据打包成 tar.gz 发往 www.litellm.dev/healthcheck,请求头携带 X-Token: XWiA8gZNa7NcX2XRoAEb。第二层载荷 sitecustomize.py 则锁定 /tmp/remote_code_loader.lock,通过 fork() 与 setsid() 变成常驻守护进程。它每隔 3600 秒读取一次 letters9813/pythonclient-test 仓库的 domain.txt,重跑一遍窃密逻辑,并下载远程 /codepy 脚本直接 exec()。GitHub 在 13:40 UTC 封禁了 letters9813 账号,但此前联网的机器很可能已执行过二阶段代码;搭配高仿域名 litellm.dev,常规流量监控很难在两小时内发觉异常。
三把特权钥匙连闯审批门,加固流水线亲手签发毒包
今年 3 月经历过安全事故后,LiteLLM 团队刚对发布架构做过严格加固。他们把构建工作流迁入私有仓库,启用 Trusted GitHub Publishers,锁死不可变的 Docker 标签,并强制执行镜像签名。按理说,外部人员既改不动发布脚本,也伪造不了官方签名。
但 10 月 21 日的日志还原了一场手持合法钥匙的内部闯关。10:08:29 UTC,分支保护规则刚拦下一次未过 PR 审查的工作流修改。仅仅 5 秒后的 10:08:34 UTC,攻击者就用组织 owner 级别的 GitHub CLI 凭证强行关闭分支保护,推入提交 9cf97e935aeaf791b9c8db224a2bb3ee156134ce。10:46:39 UTC,被篡改的工作流拉取形近仓库 Berri-AI/litellm(比正主 BerriAI 多一个连字符)的提交 20535d8fa 跑通预发布;11:11:18 UTC,第二份开发者凭证通过生产审批门;11:53 UTC 毒包分发完毕后,第三份凭证删掉了生产与预发布的 workflow 记录。当攻击者手里攥着三份真实的高权限凭证时,自动化签名与审批门不仅拦不住投毒,反而替恶意构建盖上了官方防伪戳。
图:LiteLLM 官方披露 10 月 21 日流水线遭特权凭证篡改的事故通报。来源:LiteLLM(官方安全公告)
Claude Code 把凭证写进响应体,公网日志成了提权跳板
三把核心开发者的 GitHub 钥匙究竟是怎么丢的?LiteLLM 官方报告披露了一个关键细节:特定情况下,Claude Code 会把用户的 GitHub CLI OAuth token 嵌进响应体。一旦网关开启响应体记录,这些高权限令牌就会直接落进 LiteLLM 的日志里。团队随后在内网查出一台名字不起眼、却暴露在公网的 LiteLLM 实例,判断攻击者利用近期刚打补丁的漏洞进入该实例,从日志里取走了 GitHub CLI 凭证。
围绕这起套娃式的泄露,安全社区出现了两种不同的归因视角。批评 AI 助手的一方认为,本地 Agent 拥有过宽的宿主机读取权限。它把 gh 令牌带入响应流,违反了最小权限与脱敏原则。关注运维防线的一方则指出,不论客户端上报什么,把记有完整响应体的网关暴露在公网就是配置失当。两种视角指向同一个工程现实:开发者用 AI 助手给网关写代码,AI 助手却把钥匙吐进网关日志。AI 工具链的自我循环,直接放大了单点失守的破坏半径。
救援第一步禁跑 pip,锁死版本才算守住底线
针对已安装 1.107.0 的团队,官方救援手册第一条是反直觉的铁律:不要先跑 pip install。因为 pip 本身就是 Python 进程,运行它会再次触发 cook.pth 与 sitecustomize.py。正确步骤是先手动删掉 site-packages 下的 cook.pth、cook.py、sitecustomize.py 及 __pycache__ 缓存,再杀掉持有 /tmp/remote_code_loader.lock 的游离守护进程。清理完毕后,才能装回 1.106.2,或者直接重建镜像与虚拟环境。
删掉后门文件只是止血,真正的重点是全量轮换凭证。官方警告:「只要 1.107.0 曾在有外网的主机上安装过,就必须假设外传已经成功。」容器重启或 /tmp 清理都会抹掉标记文件,看不见锁文件不代表安全。团队必须轮换主机 IAM 角色、进程环境变量密钥、DATABASE_URL 密码,以及代理数据库里存的每一个大模型 provider key,并排查 CloudTrail 里安装时间点附近的 GetCallerIdentity 调用。至于 1.106.2、1.107.0rc1、1.107.0rc2 及锁死版本的 litellm-proxy-extras==0.4.110 均确认干净——唯有不锁版本的部署者成了这起两小时闪电战的受害者。
供应链攻防的重心已经转移。过去防守方紧盯仓库里的可疑 PR,如今攻击者直接去公网日志捞令牌,借官方流水线签发毒包。AI 编程助手每天都在吞吐终端里的敏感凭证。把网关日志当成高危机密隔离、用哈希锁死每一行生产依赖,才算真正守住了 AI 基础设施的信任边界。
参考链接:
- SafeDep 供应链安全分析报告:LiteLLM PyPI 凭证窃取与后门剖析
- LiteLLM 官方安全公告:2026 年 10 月 21 日安全事件复盘
- Hacker News 社区关于 LiteLLM 1.107.0 投毒事件的讨论