今天早上一睁眼,手机里全是同一件事:litellm 被投毒了。群里转截图、转链接、转“谁跑 litellm proxy 的快查一下”,说实话这种场面我不太意外。过去几年 PyPI 上出现过多轮仿冒包和恶意组件,可当“被投毒”三个字落到自己天天在用的包上,第一反应一定是:我的服务器会不会已经中招了?
如果你也在这台机器、公司跳板机,或者哪怕本地电脑上执行过 pip install litellm,并且把它当成团队内部的模型网关在用,那这篇就是给你写的。我不会把网上流传的截图和哈希列表翻来覆去复读,我更想做的是把一套能在 30 分钟内跑完的自查流程完整拆给你看:litellm 到底是什么、恶意组件一般会藏在哪里、怎么确认自己的机器有没有被种下后门、万一中招了先处理哪件事、以及以后跑 litellm proxy 时可以参考的长期安全习惯。看完你至少能回答一个关键问题:我到底该不该慌。
1. 先别慌,搞清楚“litellm 投毒”背后到底是怎么回事
1.1 litellm 为什么会被盯上
litellm 从来不是冷门小工具。它本质上做的事情很像一个“模型总闸”:统一封装 OpenAI、Anthropic、Gemini、各类国产模型和自建模型接口,然后把 API Key、路由策略、负载均衡、失败重试全部集中到一层。很多团队用它跑 litellm proxy,对外只暴露一个 OpenAI 兼容端口,对内把各家模型的 Key 统一托管。
如果这一层被污染,后果不是“某个 Python 包不好用了”那么简单。恶意代码一旦进入 litellm 进程,第一眼就能看到环境变量里的各种 Key,然后它还可以继续改写请求路由、替攻击者发起模型调用。说得直白一点,这是整串钥匙挂在同一个钥匙环上的场景,投毒者只要打开钥匙环,后续所有门都能试一遍。
这也是为什么每当“某某包被投毒”的消息出来,运维和 AI 工程团队会格外紧张。litellm 的用户量太大,部署位置又太关键,攻击者盯上它完全符合成本收益逻辑。
1.2 这类投毒通常怎么传播
供应链投毒的常见套路其实很固定,常见的有三类。
第一种是仿冒包和抢注包。攻击者在 PyPI 上传名字与 litellm 极其接近的恶意包,比如多了个字母、加个横杠、后缀加上 -dev 或 -client。有人手滑复制错包名,或者某些历史遗留的自动化脚本依赖了错误包名,就会中招。这种情况在开源生态里反复出现。
第二种是依赖混淆攻击。如果你在内网维护了一个私有包,名字叫 my-company-llm-utils,但部署机器上同时配置了官方 PyPI 和私有源,而私有源里又找不到这个包,pip 就会去官方源找同名包。攻击者事先把同名包推到 PyPI,你的构建过程就会把恶意版本当“补位”装进去。
第三种是安装脚本和部署教程被篡改。很多人搜 litellm 使用教程时,会看到博主贴出“一键安装”命令,可能是 curl | sh,也可能是直接执行一段 Python。一旦这些内容来自不可信来源,里面完全可能夹带下载恶意文件的逻辑。
你可以把投毒理解为:常规下载渠道本身没问题,但总有人试图在“你拿到代码之前”和“代码跑起来之后”这两个节点之间做手脚。好消息是,这类攻击并非完全无迹可寻。
1.3 哪些机器最需要提高警惕
我给自己和朋友的排查优先级大致如下:跑着 litellm proxy 的生产服务器排第一,然后是开发机、跳板机、CI 执行机,最后才是个人电脑。
具体来说,这几类情况风险更高:
- 用 root 用户在宿主机上直接执行
pip install,并且之后用 root 启动 litellm; - 通过第三方博客、论坛或微信群里的命令安装过 litellm;
- 服务器上配了多个
--index-url或--extra-index-url,存在依赖混淆可能; - litellm 进程所在目录就是全局 Python site-packages,而且这台机器还被用于跑其他业务;
- 很久没升级 litellm,完全不知道当前版本和官方最新版本的差异。
当然,风险高不代本一定有问题。下面这套自查流程,建议按顺序跑一遍。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 三步自查:你的机器上是否有一个“可疑的 litellm”
2.1 第一步:核实“装进来的到底是什么”
很多人口中的“我装了 litellm”,其实并不清楚装的是哪一个发行版、从哪个源装的、文件落在哪里。先做一次最基础的信息收集:
bash复制python -m pip show litellm
python -m pip show -f litellm
第一条命令会显示版本、安装位置和依赖。第二条命令会列出这个包安装时带入的所有文件。看到输出后,重点看两个信息:安装来源里的 URL 是不是 pypi.org 或公司私有源;文件列表里有没有明显不对劲的 .py 或 .pth 文件。
接着找出 litellm 的实际入口文件:
bash复制python - <<'PY'
import importlib.util, os
spec = importlib.util.find_spec("litellm")
if spec:
print("入口:", spec.
