昨晚 AI Infra 群里有人扔了一条消息,瞬间炸了锅:“喔去,litellm 竟然被投毒了”。我第一反应不是震惊,而是“怕什么来什么”。LiteLLM 这个东西,说大不大,说小不小,但只要是做企业级大模型接入的人,十有八九都在用:它把 OpenAI、Anthropic、Gemini、国产各家模型全部封装成一套 OpenAI 兼容接口,还能做 Key 管理、路由、限流、预算控制。在很多公司里,LiteLLM Proxy 就是连接业务系统和模型厂商之间的唯一闸门。如果这个闸门里的代码出了问题,后果不是某个服务挂掉那么简单,而是所有上游模型 Key、所有经过网关的请求内容,都可能被劫持。
这篇文章想解决三件事。第一,这次说的“投毒”到底是怎么发生的,为什么偏偏是 LiteLLM 这种网关型组件容易被盯上。第二,如果你的机器或者服务器上跑过 LiteLLM,现在应该按什么顺序检查哪些文件、哪些配置、哪些日志,来判断自己有没有中招。第三,不管中招没有,以后怎么系统性加固,让同类攻击再进来也拿不到关键东西。文章不会劝你先重装系统,也不会让你删库跑路,但会给你一套可以照着抄的排查清单和应急步骤。
1. 先搞清楚“投毒”的对象:不是模型被改傻,是供应链和账号层被污染
很多人看到“投毒”两个字,第一反应是“大模型的回答被篡改了,模型智商下降了”。这一轮曝出来的问题并不是模型权重被篡改,而是 LiteLLM 这个基础设施组件本身被污染。基础设施一旦被污染,比单个模型出问题的覆盖面大得多:攻击者拿到的不是某一个模型的输出,而是你所有模型的调用入口、密钥、路由策略和原始流量。
1.1 LiteLLM 在生产环境里的真实位置
LiteLLM 最常见的两种用法,分别是 SDK 模式和 Proxy 模式。SDK 模式就是在业务代码里直接调用 litellm.completion(),把不同模型厂商的差异隐藏在一个库后面。Proxy 模式则是单独跑一个网关服务,业务系统只认这个网关的地址和 Key,网关再负责把请求转发给 OpenAI、Anthropic、Gemini 等真实厂商。
大多数上点规模的公司都会用 Proxy 模式,因为 Proxy 能集中管理 Key、做预算控制和请求日志,还能在不改业务代码的情况下切换模型供应商。这带来了一个非常危险的结果:这个进程天然握有大量上游厂商的真实 API Key,而且所有业务请求都会经过它。对攻击者来说,这就是“一把钥匙能开一栋楼”。投毒者选中这种组件,不是因为它叫 LiteLLM,而是因为它处在“代理所有模型流量”的枢纽位置。
1.2 这一轮“投毒”涉及的三种形态
把“投毒”这个词拆开看,至少能分成三类。第一类是最常见的供应链投毒,攻击者通过伪造同名包、依赖混淆或者篡改已发布包的方式,让安装者把恶意代码带进环境。第二类可以叫账号投毒,攻击者不一定会让引擎立即崩溃,而是在数据库里种下影子 Key、后门用户,之后随时可以用合法身份调用网关。第三类我习惯叫标签投毒或路由投毒,攻击者改掉模型列表、路由标签或 endpoint 配置,把正常请求悄悄引到攻击者自己的服务上。
这一轮曝光的事件里,三类形态几乎是串成一条链的:恶意安装包进入机器,先偷配置里的 Key;攻击者再用偷到的管理权限创建虚拟 Key、修改路由配置;最后整个网关都在替攻击者打工,但表面上看服务一直没有中断,监控报表也很正常,只有费用明细和某些日志能露出马脚。
1.3 为什么排查通知里会提到“mini shai-hulud 蠕虫”
这次社区流传的排查通知里出现了一个名字“mini shai-hulud”,越看越像是一次针对 LiteLLM 的横向扩散测试。它的思路大概是:如果一台 LiteLLM Proxy 的管理 Key 是弱密钥、默认密钥,或者已经通过供应链投毒泄漏出去,攻击者就会调用管理接口生成更多的合法 Key,然后从这台机器跳到同网段的其他实例,继续重复同样操作。
这个蠕虫最讨厌的地方是它不破坏文件、不删数据,也不让进程崩溃,所以常规的“机器有没有变卡”“服务有没有挂”根本发现不了。它只是在账号体系和路由配置里慢慢“养蛊”。如果你的网络里有多个 LiteLLM 实例,或者同一个管理 Key 被多套环境共用,扩散速度会非常快。这也是为什么光看进程列表和 CPU 占用没有用,真正要看的是 Key 的产生记录和路由配置有没有异常变化。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 本地环境自测:5 分钟找出常见中毒痕迹
下面这套检查流程是给“怀疑自己中招”的人准备的。顺序很重要:先看安装物,再看进程和网络外联,然后翻配置和数据库,最后查日志和路由。每一步都不需要另外装什么高级工具,纯命令行就能完成。
2.1 先看装了什么,而不是急着卸载
多数人听到“投毒”后的第一反应是 pip uninstall litellm。先别急,卸载动作会把现场破坏掉。正确的做法是先确认当前环境里到底装了哪些包、来自什么位置、版本号对不对。
bash复制# 查看所有与 litellm 相关的包
pip list --format=freeze | grep -i litellm
# 查看 litellm 的安装详情
pip show litellm
# 确认运行时实际加载的文件路径
python -c "import litellm; print(litellm.__file__, litellm.__version__)"
需要特别注意的是,pip show 显示的版本号正常并不等于安全。供应链投毒有时会做成高仿包,比如把真实 LiteLLM 的版本号抄过来,但 Home-page、作者邮箱、文件结构都和官方不一致。也有另一种更隐蔽的情况:恶意代码被写成依赖项,藏在某个不起眼的小工具包里,LiteLLM 本体完全正常。所以要结合 pipdeptree 看依赖树,确认有没有突然多出来的包:
bash复制# 查看依赖树
pip install pipdeptree
pipdeptree | grep -i litellm -A 20
如果发现依赖树里多了不认识的库,或者 litellm 目录里出现了官方版本中没有的 .py 文件,就要提高警惕了。还有一种容易被忽略的检查点:Python 的 sitecustomize.py、usercustomize.py、.pth 文件,它们会在解释器启动时自动执行,只要被塞进一行恶意代码,整个虚拟环境里所有 Python 程序都会被殃及。
2.2 看进程和网络外联,建立域名白名单
如果 LiteLLM 或恶意代码正在和外部通信,进程级联查一般能看到蛛丝马迹。
bash复制# 查看是否有 litellm 相关进程
ps aux |
