2026 年第二次了。同一个包、同一个手法、同一个目标——这是 LiteLLM 这年头一回栽、年末又栽了一遍的意思。

先说这次的手法,跟上次几乎一模一样:往 site-packages 根目录丢几个文件,靠 Python 的启动机制自动跑。具体来说,恶意 wheel 会放进去三个文件:cook.pth(内容只有一行 import cook)、cook.py、还有一个 sitecustomize.py。

.pth 和 sitecustomize 这两个东西,Python 每次启动都会执行。所以根本不需要你 import litellm——pip、pytest、Jupyter,随便哪个一起来,cook.py 就跑起来了。

跑起来之后它做的事,才是这条值得写的原因。cook.py 收集:AWS / GCP / Azure 的凭证(还会用 STS 的 GetCallerIdentity 先验证能不能用)、K8s / Docker / Git 配置、npm / PyPI 的 token、SSH / GPG / TLS 私钥、浏览器里的密码和 cookie、/proc/*/environ,以及——最关键的一项——LiteLLM Proxy 自己的 LiteLLM_CredentialsTable 和 LiteLLM_ProxyModelTable。前者是网关里存的所有模型厂商 key,后者是路由表。

一个集中管模型的网关,被从里面把钥匙串整个端走,这是这次最扎心的地方。

收集完,AES-256 加密、RSA-4096 包一层钥匙,POST 到 www.litellm.dev/healthcheck,User-Agent 装成 IE7。sitecustomize.py 还会再起一个 detached 守护进程,每小时去 GitHub raw 拉 domain.txt 指向的地址、exec() 一段没签名的代码——也就是挂了个级联,C2 地址随时能换。

怎么进来的?发布流水线被攻破,恶意包是从一个仿冒仓库 Berri-AI/litellm(比正牌少一个字母 i)构建的。最要命的一点在这:GitHub 上 v1.107.0 那个 tag 是干净的,只对比 tag 的 review 什么都看不出来。

影响版本:litellm==1.107.0(7 个 wheel + sdist);镜像 tag v1.107.0 / latest / main-latest / main-stable。时间窗(UTC)——10/21 11:39–13:23 之间 pip install 抓到过 1.107.0 的环境;11:46–14:20 之间拉过上面那几个镜像/tag 的容器。tag 后来被删了,但已经被拉下去的镜像还在。企业私有 registry 里的版本不受影响。

修复版本:没有「修复版」。回退并锁定 litellm==1.106.2(按 hash 锁),镜像按 digest 锁。

一条自查:pip show litellm | grep -E '^(Version|Location)',版本是 1.107.0 就是中招;再去 site-packages 目录下看有没有 cook.pth / cook.py / 异常的 sitecustomize.py,以及 /tmp/remote_code_loader.lock。

处置上有个坑要单独提:受影响的环境里别急着先跑 pip install——一跑 pip,cook.pth 又被触发一次。正确顺序是先把那三个文件手工删掉、把守护进程杀掉,再重建 venv 或镜像。而且注意,光是卸掉 litellm 这个包目录,不会删掉这三个启动文件,也不会停掉 loader。最后一条:只要这台机器出过网,就假设东西已经出去了,key 全部轮换。

这种「加固过一次,不等于安全」的事,之前也写过一回:rclone 那次自动更新,认了一行没签名的校验值——同样是信任链上某一环没守住。还有 GitLab 的 CI 洞,也是发布链路被人从中间插了一手。包是从哪来的、构建它的是谁,这条链现在比以前任何时候都值得多看一眼。

(这次是 2026 年 LiteLLM 第二次被投毒。3 月那次是 TeamPCP 经 Trivy 偷到 PyPI token,发的 1.82.7 / 1.82.8。)

原始来源:LiteLLM 官方安全公告《Security incident - Oct 21, 2026》:https://docs.litellm.ai/blog/security-incident-oct-21-2026