LiteLLM受污染版本的排查与响应
文章称LiteLLM 1.107.0的PyPI包及容器制品遭污染,相关制品约两小时后被撤下,较早版本和私有企业版本据称不受影响。恶意文件落在包目录之外的Python库目录,排查范围需覆盖网关、开发机和构建环境。
AI 深度解读
LiteLLM 1.107.0 这次供应链事件,最需要记住的是:恶意代码可以借 Python 启动机制执行,应用没有导入 LiteLLM,也可能中招。卸载包之后,启动文件还可能留在环境里。
原文把应急处置和上游失守过程串了起来:先找到受影响环境,再从可信环境重建、轮换凭据;而攻击入口,是一把泄露后未撤销的密钥,以及 Agent 平台持有的组织所有者令牌。以下事实均按原文转述,阅读重点是这些机制和处置边界。
没有导入 LiteLLM,为什么也可能中招
按原文引用的 LiteLLM 公告,恶意 litellm==1.107.0 于 2026 年 10 月 21 日发布到 PyPI 和容器仓库。更早版本安全,私有企业发行版客户未受影响。恶意制品在线约两小时:PyPI 发布在 13:23 UTC 前被冻结,Docker 镜像在 14:20 UTC 前移除。
两小时足以让开发机、构建节点和线上网关拉到问题版本。
关键不在 LiteLLM 的业务代码,而在 Python 的启动过程。Microsoft 分析发现,恶意 wheel 在 purelib 数据目录携带 cook.pth、cook.py 和 sitecustomize.py,安装后落入环境的库目录,位置在 litellm 包文件夹之外。
Python 启动时,site 模块会执行 .pth 文件中以 import 开头的行,并尝试导入 sitecustomize。其中 cook.pth 只有一行:
import cook
这行代码用于启动凭据收集器,收集任务运行在守护线程中。要留意的是,触发它的是解释器初始化过程,应用无需主动导入 LiteLLM。
另一个 sitecustomize.py 包含面向 Unix 的加载器,设计上可以下载并执行额外 Python 代码,但 Microsoft 没有确认这条路径成功完成远程获取。原文还提到,一个 Windows 案例中,安装无关依赖的普通 Python 调用就激活了收集器。
排查可疑环境时,启动 Python 本身就可能再次触发攻击。
收集器的目标覆盖 AI 助手、IDE 和 MCP 配置、Git 与包管理器凭据、AWS、Azure CLI 和 Google Cloud 缓存、Kubernetes 服务账号文件、Docker 配置、浏览器凭据、Shell 历史,以及 SSH、GPG、TLS 材料。它还读取进程环境变量,在 Linux 上尝试通过 procfs 读取其他可访问进程的环境。
代理主机上,另一个模块可通过 Prisma 读取两张 LiteLLM 数据库表的部分字段。收集结果使用每次运行生成的 AES 密钥加密,再用内置 RSA 密钥包装,发送至仿冒域名地址 hxxp://www[.]litellm[.]dev/healthcheck。
这里必须守住证据边界:代码里列了某种目标,不代表已经成功读取或外传了它。
正确的处置顺序,为什么不是先卸载
原文整理的处置流程,可以分成定位、取证、重建和凭据失效四步。
首先找全副本。检查已安装环境、pip 和 uv 缓存、内部镜像源、锁文件、构建产物及容器镜像中的 1.107.0。容器还要核对实际拉取的摘要和时间。latest 是可变标签,无法证明当时部署的内容安全。
接着隔离主机,在安全允许时停止 Python 进程,并阻止自动化重新拉起。Microsoft 明确要求:取证期间不要运行 python、pip,也不要运行任何会调用受影响解释器的程序。应从已知干净的机器,使用可信工具检查文件系统。
判断影响范围时,需要交叉核对文件哈希、Python 进程父子关系、.pc_e_ 临时暂存目录、收集域名连接记录,以及相关身份后续的使用行为。发现问题包是调查入口,不能直接推导出所有凭据都已被盗。
恢复应从经过验证的制品重建环境和镜像,并确认库路径里不再有恶意 cook.pth、cook.py、sitecustomize.py。这些文件位于包目录之外,所以卸载 LiteLLM 或删除发布标签都不足以完成恢复。
最后,从干净机器轮换受影响身份能够访问的凭据,包括模型供应商密钥、云与工作负载凭据、CI/CD Secret、源码和镜像仓库令牌、SSH 与 GPG 密钥、AI 编程工具令牌。代理主机还要覆盖存储的供应商凭据和 DATABASE_URL。
在受感染工作站上换密钥,可能把新密钥再次交给收集器。
轮换之外还需撤销会话。原文引用 Entra 紧急撤销指引,提醒修改密码不会立即使全部活动令牌失效;并提到,同周的 Railway 事件也适用从干净环境轮换的原则。
发布流程为什么会被一路打穿
这条攻击链并非从发布当天开始。
2026 年 5 月 27 日,一份提交到公开仓库的配置文件泄露了 LiteLLM 内部 Agent Platform 的主密钥。团队用强制推送覆盖提交,也识别出需要撤销密钥,但据其复盘,撤销没有执行。
该平台允许自托管 Agent 创建拉取请求,因此保存了 GitHub 令牌。问题在于,它持有的是组织所有者的 GitHub CLI OAuth 令牌,没有使用服务账号,也没有收窄权限。
10 月 10 日,攻击者用泄露的主密钥调用平台 API,取得该令牌,再运行临时 CI 工作流,把仓库 Secret 发往外部地址,并拿到另外两名维护者的令牌。
10 月 21 日,攻击者使用所有者令牌绕过发布仓库的分支保护,将其重定向到仿冒 fork;用一名维护者的令牌批准生产发布,再用另一名维护者的令牌删除运行记录。当周,发布审批规则恰好放宽为任意两名工程师即可批准。
这段复盘暴露的是连续的权限问题:泄露凭据没有失效,Agent 持有人类高权限身份,临时工作流又能接触敏感 Secret。覆盖 Git 历史无法撤回已公开的密钥;审批人数也不能单独代表安全程度,还要看审批身份是否独立、权限能否被同一条攻击链获取。
我的判断
原文最有价值的地方,是解释了为什么常见动作会失效:没导入包仍可能执行,卸载包仍可能残留,改密码仍可能留有活动令牌。这些判断有具体机制支撑。
预防建议则需要按能力边界理解。带哈希的锁文件可以让未经审查的升级失败:pip 哈希检查模式要求每项依赖提供哈希,不匹配就停止安装。但如果团队审核时把恶意版本及其哈希一起纳入,哈希校验仍会通过。它验证制品一致性,无法判断制品是否恶意。
容器使用 @sha256: 摘要能避免 latest 悄悄变化,也不能保证被固定的镜像安全。内部镜像源增加审核和新版本等待期,可能避开这次约两小时的窗口,但原文没有给出对照数据,无法据此确定等待多久才合适。
限制出站 HTTP、减少长期密钥驻留环境变量、从密钥库按需获取短期凭据,都有明确的风险收缩方向。网关通常需要连接模型供应商和数据库,未必需要访问任意外部域名。不过,实际效果取决于网络规则和身份权限;短期凭据在有效期内也可能被利用。
原文引用了官方公告与 Microsoft 分析,但输入没有附上完整报告、文件哈希和镜像摘要清单。它适合帮助团队理解应急顺序,不能直接充当完整的取证手册。
能拿来做什么
- 如果前端或全栈项目通过 LiteLLM 接入模型,把排查范围延伸到开发机、Python 工具环境和 CI 构建节点,并保留容器摘要及拉取时间。
- 把「隔离后用可信工具检查」写进依赖事件处置流程,避免习惯性运行
pip查询版本;确认受影响后,从可信制品重建环境。 - 给能创建 PR 的 Agent 配置独立且权限受限的身份,检查 CI Secret 是否仅对受保护分支和获批工作流开放,并审查 GitHub Actions 的
persist-credentials配置。 - 为 AI 网关建立凭据清单,覆盖模型供应商、数据库和云身份;发生事件时,从干净机器执行轮换与会话撤销,避免只处理代码仓库里可见的密钥。