PyPI 上的 litellm==1.107.0 被投毒了。里面塞了一个偷凭据的程序,还留了一个能远程下命令的后门。
它偷走的东西里有一项特别扎眼——AI 工具的登录凭据。Claude、Codex、Gemini、Qwen、Cursor、Windsurf、Kiro、Copilot、HF token 全在清单里。
装过这个版本的,AI 工具的 token 建议全部换一遍。
本文目录
一、这事跟你有没有关系
二、它到底干了什么
三、偷走了什么
四、你现在该做什么
五、技术细节( interested 可以跳过)
一、这事跟你有没有关系
LiteLLM 是一个 LLM 代理工具,简单说就是帮你统一管理各家模型 API 的中间层。很多人在用它把 Claude Code、OpenCode 之类的工具接到不同厂商的模型上。
判断要不要紧张,就一句话:
10 月 21 日前后,你的机器或 CI 里装过
litellm==1.107.0吗?
装过 → 往下看,第四节的处置步骤跟着做。没装过 → PyPI 已经下架了,现在装不到。但还是建议跑一下第四节第 2 步,确认一下。
发布时间是 10 月 21 日。官方当天发了事件报告,当天下午全部处置完。
二、它到底干了什么
投毒的手法不复杂,理解了就不可怕。
攻击者是怎么混进去的
LiteLLM 官方的仓库叫 BerriAI/litellm。攻击者建了一个名字几乎一样的仓库Berri-AI/litellm——中间多一个连字符。
1.107.0 这个版本,是从这个仿冒仓库构建出来的。构建过程中,有人在配置文件里加了一行,让构建工具顺手把一个叫 cook 的文件夹塞进了安装包。
也就是说:代码本身没被改,是构建过程被动了手脚。GitHub 上看到的源码是干净的。
装完之后会发生什么
安装的时候,有三个文件被放进了你 Python 的库文件夹里:
|
|
|
|
|---|---|---|
cook.pth |
|
import cook
|
cook.py |
|
|
sitecustomize.py |
|
|
最需要理解的一点:你根本不用 import litellm。
.pth 文件是 Python 的一个机制——放在库文件夹里的 .pth 文件,会在你每次启动 Python 的时候自动执行。sitecustomize.py 也是,Python 启动时的标准钩子。
所以哪怕你装完就忘了,从来没用过 litellm,只要在这台机器上跑过任何 Python 程序,它就已经执行过了。
偷一次就够
cook.py 是在后台线程里跑的,跑一次就结束,不需要一直和攻击者保持联系。
这一点很重要:它跑完就算你断网,也已经是失陷状态了。不用担心「我现在断网还来不来得及」。
后门是持久的,现在处于休眠状态
sitecustomize.py 另外起了个后台守护进程,每小时做三件事:
- 去 GitHub 上读一个文件,里面写着攻击者的服务器地址
- 如果地址有内容,再偷一遍凭据
- 去那个服务器下载一段代码,直接执行
多家来源确认,那个文件从没被填进过真实地址。官方 Issue 给的时间点是 10 月 20 日上午。
所以这层现在是睡着的。但官方原话是:操作者只要提交一次代码就能重新唤醒。
Windows 上这个守护进程起不来(会静默失败),但偷凭据那部分照跑。
三、偷走了什么
下面是官方列的完整清单。你可以从里面找到自己在意的东西。
浏览器
- Chrome 保存的密码(解密后)、浏览记录、Cookie
- Firefox 的
logins.json和key4.db
开发相关
- SSH 私钥
- 命令行、数据库、REPL 的历史记录
- AWS、阿里云、谷歌云、k8s、docker 等云服务的登录凭据
- git、npm、pip、maven、gradle 等包管理器的配置
- 各种
.env文件、证书文件(.pem.key.pfx)
CI/CD
- k8s 的服务账号 token、
/run/secrets/目录 - Jenkins、GitLab Runner、Vault、Terraform
AI 工具凭据 ← 如果你只看一段,看这个
- Claude、Codex、Gemini、Qwen、Cursor、Windsurf、Kiro、VS Code MCP、Copilot、HF token
运行中的程序
- 机器上所有能读到的进程的环境变量
- 如果你设过
DATABASE_URL这个环境变量,它会连上数据库,把你代理里存的每一个模型厂商的 API key 都导出来
云厂商的临时凭据
- AWS、GCP、Azure 上机器角色的临时密钥
私钥
- GPG 私钥、TLS 私钥
传到哪去了
数据用强加密处理过,直接抓包解不开。压缩后发到这个地址:
路径伪装成「健康检查」,会混在正常的 LiteLLM 流量里。
四、你现在该做什么
官方给了六步,按顺序做。
1. 别先跑 pip install
如果环境已经脏了,你敲任何 Python 命令——包括 pip 自己——都会把那两个文件重新执行一遍。
所以先做第 2 步。
2. 手动删文件
在每一个装过 litellm 的 Python 环境里,把这几个文件删掉:
Windows 用户搜一下 C 盘,把这些文件名挨个找出来删。
3. 干掉后台进程
它占着一个锁文件:
Linux 和 macOS 上关掉对应的 Python 进程就行。
4. 重装,锁死版本
官方更推荐的做法是:把虚拟环境或 Docker 镜像整个重建一遍,比打补丁干净。
5. 装过就默认已经被偷了
官方的原话是:默认假设外传已经成功。
确实有个标记文件能确认外传发生过,但没有这个文件不代表没事——容器重建、临时目录清理都会把它删掉。
别拿这个当安全感。
6. 换掉所有凭据
这是最麻烦但最关键的一步。官方列了这些:
- 云服务上给机器配的角色权限(IAM role)
- LiteLLM 数据库里存的所有模型厂商 API key,还有 master key 和 virtual key
- 数据库连接密码(
DATABASE_URL里的) - 任何出现在进程环境变量里的密钥
AI 工具的 token 也要换。这是最容易漏的一项——很多人记得换数据库密码,忘了换 Claude 和 Codex 的登录凭据。
想确认有没有被用过,去云厂商的审计日志里查:安装时间附近,有没有机器角色发起过「我是谁」这类身份查询;然后看这个角色的密钥有没有从公司网络外面被使用过。
五、技术细节
这节是给想深挖的读者的。
时间线
|
|
|
|
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
11:21 这个时间点得说清楚。 官方 Issue 写的是「安装包于 11:21Z 左右构建完成」,但这只是 Linux 一个平台的时间戳,Windows 那批是 11:37。Socket 从容器构建溯源里挖出来的是另一个区间:10:51:23 到 11:06:31。两个数字指向的是不同环节,一个是构建执行,一个是产物时间戳。
13:20 和 13:23 也不是一回事。 Wiz 和 Datadog 记的 13:20 是「隔离」,官方 Issue 标的 13:23 才是完全下架。差 3 分钟,应该是两个动作分开做的。
事件是 Upwind 安全研究团队报出来的。他们没执行任何代码,纯静态解码就把 payload 还原了。
受影响的安装包
7 个全部受影响,覆盖所有主流平台:
源码包 litellm-1.107.0.tar.gz 里没有 payload 文件,但配置文件一样被改了。
Docker 那边也没幸免。ghcr.io/berriai/litellm{,-database,-non_root} 和 docker.io/litellm/litellm 的 latest、main-latest、main-stable 标签,都曾经指向带毒镜像。
确认干净的版本
官方逐个查过:
加密方案
数据用 AES-256-CBC 加密,密钥用 RSA-4096-OAEP 包装。
关于构建溯源
官方在给维护者的诉求里提到,截至事件发生时 litellm 还没有可验证的 PyPI attestation,所以用户没法区分被篡改的构建和正常构建,建议迁到 Trusted Publishing。
补一句背景:LiteLLM 在今年 3 月那次供应链攻击之后,已经宣布要迁了。Trusted Publishing 一般会带数字证明,所以这里说的是这次事件发生时的状态,不是说这个项目没做过改造。
互动问题:你机器或 CI 里装过 litellm 1.107.0 吗?AI 工具的 token 轮换过了吗?






