LiteLLM 被曝投毒,重点窃取编程工具凭据
据文章披露,PyPI 上的 LiteLLM 1.107.0 含恶意载荷,会搜寻 Claude、Cursor、Copilot 等 AI 编程工具的凭据,该版本已被撤下。文章提供依赖排查思路,并介绍让 uv、pip 避开刚发布版本的配置方向。
AI 深度解读
一次 pip install -U litellm,可能把模型接口库变成凭据窃取入口。按原文披露,2026 年 10 月 21 日上传到 PyPI 的 litellm==1.107.0 含有恶意代码,随后被下架,原文建议使用 1.106.2。
这篇最有用的地方,是解释了为什么检查 GitHub 源码和运行 pip show 都可能漏掉风险,并给出一个成本很低的防线:让包管理器默认避开发布不足 3 天的版本。以下事件细节来自原文转述,不能当作本站独立验证的调查结果。
为什么源码干净,装进环境的包仍然有毒
原文称,这是 LiteLLM 当年的第二次失陷,与 3 月事件无关。LiteLLM 为 Claude、GPT 等模型提供统一接口,可能被 agent 或代理间接安装。你没主动选过它,也可能已经在用。
这次攻击的关键在交付环节:GitHub 上的 v1.107.0 标签是干净的,恶意文件只出现在上传到 PyPI 的 wheel 中。wheel 是 Python 的安装分发文件,用户实际装进去的内容,未必与仓库里看到的源码一致。
攻击也不需要等业务执行 import litellm。按原文分析,wheel 向 site-packages 放入 .pth 和 sitecustomize.py,利用 Python 启动时的加载机制触发载荷。同一环境中的其他 Python 进程也会成为入口。它还启动守护进程,每小时拉取并执行远程代码,服务器地址从 GitHub 上的文件读取。
发布时间同样降低了戒心。此前几天,1.107.0rc1、rc2 正常发布,接着出现正式版很符合预期。对习惯及时升级依赖的人来说,这看起来就是一次普通更新。
仓库源码可信,不能直接推出安装产物可信。
真正要排查的是凭据和全部环境
Flatt Security 的分析将收集目标分为 16 类。AI 开发者最容易受影响的,是 Claude、Cursor、Copilot、Gemini CLI、Codex CLI、Windsurf、Aider、OpenCode 和 Hugging Face 的相关凭据。
范围还包括 .env、私钥、SSH 密钥、云凭据、浏览器密码和 shell 历史。原文称,载荷会通过 /proc/*/environ 读取自身及其他进程的环境变量;通过这种方式传入的 ANTHROPIC_API_KEY、OPENAI_API_KEY 也在风险范围内。这条路径主要对应 Linux 环境,不能理解成所有系统都采用相同的窃取方式。运行 LiteLLM proxy 的团队,还要考虑代理数据库保存的 provider keys。
Claude Code 则要区分凭据存放位置。原文援引官方文档称,macOS 使用 Keychain,Linux 和 Windows 使用 ~/.claude/.credentials.json;macOS 在 Keychain 不可写时也会回退到该文件,例如通过 SSH 使用时。CI 和服务器环境不能因为没有桌面登录就被排除。
作者在自己的 Mac 上检查后没有发现异常,但这只是一次个人排查结果。pip show 仅检查当前环境,无法覆盖 uv tool、pipx 或其他虚拟环境。原文建议搜索安装元数据目录:
find ~ -maxdepth 8 -type d -iname 'litellm-*.dist-info' 2>/dev/null
要看的是目录名中有没有 litellm-1.107.0.dist-info。同时也要看清 ~ 和 -maxdepth 8:命令覆盖的是指定目录及深度,不能据此宣称整台机器没有风险。
接着检查 requirements*.txt、pyproject.toml、uv.lock、poetry.lock。原文用 grep -rIl -i 'litellm' 搜索 ~/code 中的这些文件,它找到的是引用位置,还需要确认是否锁定了 1.107.0。即使上游已下架,内部镜像或缓存仍可能让重建环境的人再次安装。
原文给出的落地痕迹是 /tmp/.pc_once_72129118c59f5636c0bb 和 /tmp/remote_code_loader.lock,进程筛选命令为 ps aux | grep -E 'cook|remote_code_loader' | grep -v grep。按其分析,前一个文件代表数据已经发送,锁文件或匹配进程代表后门在运行。macOS 重启会清理 /tmp,所以找不到文件不能单独作为安全证明。
延迟 3 天安装,为什么能挡住这一次
原文称,恶意版本在线不足一天;Flatt Security 的 registry proxy 设置了 3 天隔离期,其用户未受影响。这支持一个具体判断:对这次短暂暴露的恶意版本,等待窗口有用。
uv 可以按每个文件的上传时间过滤版本,exclude-newer 接受 24 hours、1 week、3 days 或 ISO 8601 格式的 P3D。下面的配置还展示了紧急补丁的例外处理:
[tool.uv]
exclude-newer = "3 days"
exclude-newer-package = { cryptography = false }
要留意最后一行:cryptography = false 会让该包豁免等待期,并非阻止安装。这里只是演示例外机制,不应直接当作团队默认配置。写进全局 ~/.config/uv/uv.toml 时,要省略 [tool.uv]。
pip 对应的命令是 pip install --uploaded-prior-to P3D litellm,也可以通过 export PIP_UPLOADED_PRIOR_TO=P3D 设置默认值。它要求索引提供上传时间,原文称 PyPI 支持;不识别参数时,作者建议升级 pip,但没有给出最低支持版本。
等待也会延迟安全修复。原文建议 pip 在单次紧急安装时取消该环境变量,让绕过等待成为有意识的操作。Node.js 读者可以关注 pnpm 的 minimumReleaseAge,不过原文没有展开其配置格式和版本要求。
我的判断
我赞同把依赖发布时间纳入安装策略。锁文件能固定版本,却不能保证第一次锁入的版本可信;审查仓库源码,也覆盖不了分发文件被替换的问题。等待窗口补的是发现和下架恶意包所需的时间。
但 3 天不是安全认证。原文没有提供大规模对照数据,无法据此判断它能拦住多少供应链攻击。更长潜伏期的恶意版本仍可能通过,紧急补丁也需要例外流程。这是有具体事件支撑的防御经验,不能替代凭据隔离和安装产物校验。
原文最后提到,Claude Managed Agents 中类型为 environment_variable 的 Vault 凭据,在沙箱内只有占位符,真实密钥在出站时替换。这个设计能减少环境变量转储造成的泄露,但适用范围很明确,不能推广为所有 agent 都具备的保护。
能拿来做什么
- 如果项目或 AI 工具可能依赖 LiteLLM,先搜索各环境的安装目录,再核对锁文件中的版本;排查路径应覆盖实际工作目录、工具环境和 CI 环境。
- 如果发现受影响版本,按原文引用的清理步骤处理,并把相关凭据按已泄露处理。除了
.env、GitHub、包仓库、SSH 和云凭据,还要轮换模型 API keys、LiteLLM proxy 保存的密钥,并通过/logout、/login等方式重新登录相关工具。 - 检查各 provider 自 10 月 21 日以来的用量记录,寻找无法解释的调用;仅卸载依赖无法撤销已经外传的凭据。
- 为日常 AI 编程环境设置依赖等待期,同时保留可审查的紧急例外。前端团队可评估 pnpm 的
minimumReleaseAge,Python 工具链则可按原文检查 uv、pip 和所用索引的支持情况。