乐于分享
好东西不私藏

月下载近亿的Python库被“投毒”!

月下载近亿的Python库被“投毒”!

整理 | 郑丽媛
出品 | CSDN(ID:CSDNnews)

如果你是一名 Python 开发者,对 pip install 命令肯定很熟悉——这是最常用的套件安装指令,可用来从 PyPI 或其它来源安装、升级与管理套件。

但就在 3 月 24 日,这个看似无害的动作,差点变成一场席卷整个开源生态的安全灾难:出问题的是 AI 开发圈中使用非常广泛的 Python 库 LiteLLM,它在 PyPI 上发布的两个版本(1.82.7 和 1.82.8)被发现包含恶意代码。

简单介绍一下LiteLLM 的作用很简单:统一调用不同大模型 API,让开发者可以在 OpenAI、Anthropic、Google 等模型之间自由切换。因此,它被大量 AI 项目当作底层依赖使用,月下载量高达 9700 万次。

换句话说:它一旦出问题,影响范围将呈指数级放大。

一次“绕过流程”的投毒发布

事情的起点,是当天 10:52(UTC)发布到 PyPI 上的一个新版本:litellm 1.82.8。随后 FutureSearch 团队很快确认,1.82.7 版本同样受到污染。

表面上,这只是一次普通的版本更新。但很快有人发现不对劲:PyPI 上出现了新版本GitHub 仓库却没有任何对应的 release 或 tag显然该版本的发布应该绕过了正常流程

更关键的是,更新之后的版本中夹带了一个不起眼却极其危险的文件——.pth 文件。

对于不熟悉 Python 机制的人来说,这里有个关键点:.pth 文件可以在 Python 解释器每次启动时自动执行代码。也就是说只要安装了这个版本:即使你没有主动调用 LiteLLM,恶意代码也会在后台悄悄运行。

幸运乌龙攻击代码出了“低级 Bug”

这次恶意攻击之所以被快速发现,并不是因为防御做得有多好,而是——攻击代码自己出了 Bug。

最早发现异常的是 FutureSearch 工程师 Callum McMahon。当时,他正在测试一个 Cursor MCP 插件,却遇到了一个诡异现象:Python 一启动,机器直接卡死(内存被耗尽)。

他排查后发现:

问题来源于新安装的 LiteLLM 包 

存在一个 34KB 的 .pth 文件

文件内容经过双重 base64 编码

正如上文所说由于 .pth 文件在每次 Python 启动时都会执行恶意代码会启动一个 Python 子进程子进程再次触发 .pth无限递归之后最终形成一个指数级“fork 炸弹”

由此导致的结果非常直接:内存占用飙升系统迅速卡死最终机器直接崩溃

本来,这只是攻击代码中的一个“低级 Bug”正是这个 Bug 引起了工程师的警觉,才让这次攻击浮出水面——正如 Andrej Karpathy 所说:

“如果攻击者不是用 Vibe Code 写代码(而出了 Bug),这次攻击很可能会隐藏几天甚至几周。”

一旦中招,你的开发环境基本“全盘透明”

据 FutureSearch 介绍这次攻击的恶意代码设计得相当“专业”,主要分为三个阶段:信息收集、数据外传和横向扩散。

首先,它会扫描开发者机器上的敏感信息,包括:SSH 私钥和配置、.env 文件中的各种 API Key、AWS、GCP、Azure 等云平台凭证、Kubernetes 配置、Git 凭证、数据库密码、Shell 历史记录,甚至加密货币钱包文件。同时,它还会主动读取环境变量,并访问云环境中的元数据接口,进一步挖掘可用权限。

接下来,这些收集到数据不会明文发送,而是经过精心处理

使用 AES-256-CBC 加密数再用 4096 位 RSA 公钥加密会话密钥打包成 tar 文件发送到 https://models.litellm.cloud/——这个域看似“官方”实际上并不属于 LiteLLM 的基础设施。

其实到这一步为止,问题已经足够严重但真正危险的是它的第三步从“偷数据”到“接管集群”

一旦检测到当前环境中存在 Kubernetes 配置,这段恶意代码会尝试进一步扩散:

读取整个集群中所有 namespace 的 secrets 

在每个节点上创建特权 Pod 

挂载宿主机文件系统 

随后,它会在系统中写入后门:/root/.config/sysmon/sysmon.py,并注册 systemd 服务,实现持久化控制——这意味着:攻击者不仅能读取你的数据,还能长期“接管”你的整个集群,且悄无声息。

如果这件事只影响 LiteLLM 用户,问题还不算最糟。但现实是,影响范围远不止如此:如上文所说LiteLLM 自身的月下载量已高达 9700 万次,同时它又被大量 AI 项目作为底层依赖使用,因此下载这些项目同样也会受到影响。

如 Karpathy 提到的 DSPy 等框架,都间接依赖 LiteLLM。所以,哪怕你只是执行了一次 pip install dspy也可能被“顺带感染”——这种通过供应链传播的攻击,就像病毒一样,会在整个软件生态中扩散。

所幸根据目前披露的信息,被投毒的版本在 PyPI 上存在的时间不到一小时,随后被紧急下架。安全团队也迅速介入,社区开始排查和修复影响范围。到目前为止,没有大规模用户数据泄露的报告,可以说是不幸中的万幸。

如果你中招了,该怎么办?

如果你在 3 月 24 日之后安装过 LiteLLM,请立即执行以下操作:

1. 检查版本

pip show litellm

重点关注是否为 1.82.7 和 1.82.8 版本

2. 清理环境

pip cache purgerm -rf ~/.cache/uv

并删除相关虚拟环境中的 LiteLLM

3. 检查后门

重点查看:

~/.config/sysmon/sysmon.py

~/.config/systemd/user/sysmon.service

Kubernetes 用户需检查异常 Pod(如 node-setup-*)。

4. 最关键的一点:立即更换所有凭证

记住一个默认原则:只要安装过恶意 LiteLLM 版本设备所有凭证一律视为泄露。其中包括:SSH Key云服务密钥Kubernetes 配置API Key 数据库密码

写在最后

关注此事的 Karpathy在 提到一句话:

“像这样的供应链攻击,是现代软件中最可怕的事情之一。”

原因在于,今天的软件开发,已经建立在庞大的依赖体系之上:一个项目可能依赖几十甚至上百个库,每个库又有自己的依赖,最终形成一个复杂的“依赖树”攻击者只需要在这棵树的某一个角落“投毒”,就可能影响到无数的下游项目

可怕的是,一旦凭证被窃取,攻击者就可以登录云服务,接管代码仓库,并发布新的恶意版本,从而形成一个不断扩散的攻击链条。

一直以来传统的软件工程都在提倡复用、模块化、不要重复造轮子尽量使用成熟的依赖库。可经过此事,这个理念正在被重新审视。Karpathy 也基于此提出一个颇具争议的观点:

在一些简单场景下,他更倾向于使用大模型直接生成代码,而不是引入新的依赖。

本质上来说,这是在用“可控的代码生成”,替代“不可控的外部依赖”——听起来可能有些“反直觉”,但在安全视角下,却并非没有道理。

参考链接:

https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/

https://x.com/karpathy/status/2036487306585268612