
紧急警告:你的 pip install 正全盘失守!
大神 Karpathy 亲自跳了出来,给这件事定了个性:Software Horror。
LiteLLM,月下载量 9700 万的 Python 库,被黑客组织 TeamPCP 植入了恶意代码。
只要你执行了 pip install litellm,你机器上的 SSH 密钥、AWS/GCP/Azure 凭证、Kubernetes 配置、Git 凭证、所有环境变量里的 API Key、shell 历史记录、加密货币钱包、SSL 私钥、CI/CD 密钥、数据库密码,全部会被打包加密,发送到黑客控制的服务器上。
全部。
NVIDIA 机器人研究主管 Jim Fan 称:
这是纯粹的噩梦燃料。过去的身份盗窃,跟 vibe agent 能干的事比起来根本不值一提。窃取凭证只是最低级的手段。它们完全可以把污染扩散到 ~/.claude、**/skills/*,甚至只是你 Agent 定期读取的一个 PDF 文件。你文件系统里的每一个文本文件,都可能成为攻击载体。每一段文字都可能是 base64 编码的病毒。
这是纯粹的噩梦燃料。过去的身份盗窃,跟 vibe agent 能干的事比起来根本不值一提。窃取凭证只是最低级的手段。它们完全可以把污染扩散到 ~/.claude、**/skills/*,甚至只是你 Agent 定期读取的一个 PDF 文件。你文件系统里的每一个文本文件,都可能成为攻击载体。每一段文字都可能是 base64 编码的病毒。
3 月 24 日上午 8:30 UTC 左右,LiteLLM 的两个恶意版本(1.82.7 和 1.82.8)被发布到 PyPI。
这两个版本在 GitHub 上没有对应的 tag 或 release,是攻击者绕过正常发布流程,直接上传到 PyPI 的。
根据 Wiz 的分析,36% 的云环境中存在 LiteLLM。
换句话说,全球超过三分之一的云环境都可能暴露在这次攻击的射程之内。
恶意版本大约在 11:25 UTC 被 PyPI 隔离,暴露窗口约 3 小时。LiteLLM 每天大约有 340 万次下载,3 小时内可能有数十万次安装。
LiteLLM 官方随后发布了安全公告,确认攻击源于此前 Trivy 安全扫描器的供应链攻击。被盗凭证被用来获取了 LiteLLM 的 PyPI 发布 token。
官方表示,已删除恶意版本、重置了所有维护者凭证、聘请了 Google 旗下的 Mandiant 安全团队进行取证分析。
不用 import 就中招
这次攻击用了一个大多数 Python 开发者恐怕都没听说过的机制:.pth文件。
一般的恶意包,需要你 import它才能触发。
.pth 触发机制对比
但 .pth文件不一样,它是 Python 的 site模块在解释器启动时自动加载的。只要这个包装在你的环境里,你跑任何 Python 脚本,恶意代码都会自动执行。
不需要 import,不需要调用,甚至不需要你的代码跟 LiteLLM 有任何关系。
你在同一个虚拟环境里跑个 python hello.py,也会触发。pip、IDE 的语言服务器、任何 Python 子进程,统统中招。
这就好比你在小区快递柜取了个包裹,结果这个包裹会在你每次开家门的时候,自动把你家钥匙复制一份寄出去。
这个机制在 MITRE ATT&CK 框架中已经有了自己的编号:T1546.018(Python Startup Hooks)。
CPython 的维护者其实已经意识到了这个风险,但至今没有做任何修补。
值得注意的是,两个恶意版本的攻击方式也不同。
1.82.7把恶意代码藏在 proxy_server.py的第 128 行,只有导入 litellm.proxy.proxy_server时才会触发。而 1.82.8直接升级到了 .pth文件,覆盖面从「用了代理模块才中招」变成了「只要 Python 启动就中招」。
两个版本之间只隔了 13 分钟。攻击者在实时迭代。
显然,这是个 vibe coding 高手
殃及池鱼
LiteLLM 本身 9700 万月下载量已经够吓人了。但更让人后背发凉的是,它其实是很多主流 AI 框架的底层依赖。
依赖树传染路径
Karpathy 称:
更糟糕的是,这个污染会扩散到任何依赖 LiteLLM 的项目。比如你执行 pip install dspy(它依赖 litellm>=1.64.0),你也会中招。其他任何依赖 LiteLLM 的大型项目同理。
更糟糕的是,这个污染会扩散到任何依赖 LiteLLM 的项目。比如你执行 pip install dspy(它依赖 litellm>=1.64.0),你也会中招。其他任何依赖 LiteLLM 的大型项目同理。
3 月 24 日当天,DSPy、MLflow、CrewAI、OpenHands 等 9 个主流项目紧急提交了安全修复 PR。
Prodigy(爆款 NLP 标注工具)的开发者也发了紧急通知:
如果你在 3 月 24 日安装过 Prodigy Company Plugins,请立刻检查是否拉入了 LiteLLM 1.82.7 或 1.82.8,因为 DSPy 是它的子依赖。
你以为你装的是一个 AI 框架,实际上你把整台机器的凭证都交出去了。
黑客的 bug
这个攻击差点就完美了。
恶意版本只暴露了大约 3 小时就被发现了。
而搞笑的是,其被发现的过程……
因为,攻击者自己的代码里有个 bug。
.pth文件的 launcher 用 subprocess.Popen启动了一个子 Python 进程来执行恶意代码。
但问题是,子进程启动时又会加载 .pth文件,然后又启动一个子进程,子进程再启动子进程……
经典的 fork bomb。指数级进程爆炸。
Fork bomb 递归爆炸
一个叫 Callum McMahon 的开发者,当时在 Cursor 里用一个 MCP 插件,这个插件把 LiteLLM 作为传递依赖拉了进来。LiteLLM 1.82.8 一装上,他的机器瞬间内存耗尽,直接崩溃了。
Karpathy 也提到了这个讽刺:
如果攻击者没有在这次攻击中「vibe code」的话,这个恶意代码可能会在不被发现的情况下存活好几天甚至好几周。
如果攻击者没有在这次攻击中「vibe code」的话,这个恶意代码可能会在不被发现的情况下存活好几天甚至好几周。
Far El(一位开发者)说自己「差一个版本就中招了,吓出一身冷汗」。
Hamel Husain(ML 工程师,nbdev 作者)则开了个黑色幽默的玩笑:
如果你喜欢从头重写所有软件,今天就是你的平反日。
如果你喜欢从头重写所有软件,今天就是你的平反日。
Google Brain 的 Lucas Beyer 也是直接乐了:
不会吧,什么硅谷奇葩事。
不会吧,什么硅谷奇葩事。
一个本该完美的攻击,被黑客自己的 bug 搞砸了。
三级火箭
恶意代码的设计,倒是挺「专业」的,分成三个阶段。
恶意代码三级火箭流程
第一阶段:扫荡。
一个 332 行的凭证收割脚本,系统性地扫描你机器上所有能找到的敏感信息。SSH 密钥、云凭证、数据库配置、环境变量、加密货币钱包,甚至自己实现了一套完整的 AWS SigV4 签名流程,去调 Secrets Manager 和 SSM Parameter Store 的 API 来偷取更多密钥。
连 /etc/shadow(密码哈希文件)都不放过。
第二阶段:加密外传。
把收集到的所有数据打包成 tpcp.tar.gz(注意这个文件名,tpcp 就是 TeamPCP 的缩写),用 AES-256 加密,再用一个 4096 位的 RSA 公钥加密会话密钥,然后 POST 到 models.litellm.cloud。这个域名看着像 LiteLLM 的官方基础设施,其实是攻击者在 3 月 23 日刚注册的。
只有持有对应 RSA 私钥的人才能解密这些数据。即使拦截了网络流量,也无法还原内容。
第三阶段:横向扩散。
如果发现机器上有 Kubernetes 的 service account token,恶意代码会去读取集群内所有 namespace 的 secrets,然后在每个节点上部署一个特权 Pod(名字叫 node-setup-{节点名}),挂载宿主机的整个文件系统,在宿主机上安装持久化后门。这些 Pod 运行在 kube-system命名空间里,设置了 tolerations确保连控制面节点也不放过。
另外还会在本地悄悄装一个 systemd 服务,伪装成「System Telemetry Service」,每 50 分钟从 checkmarx.zone拉取新的指令。
机灵的是,这个进程名还伪装成 PostgreSQL,在进程列表里几乎看不出异常。
连环猎杀
而 TeamPCP 这个名字,最近一个月在安全圈已经出现了太多次了。
LiteLLM 只是他们最新的一个目标。
TeamPCP 连环攻击链时间线
根据 Snyk 的分析,这已经是他们从去年 12 月开始的系列攻击的第九阶段。整条攻击链是这样的:
2 月 28 日,他们利用 Trivy(Aqua Security 的漏洞扫描器)的一个 pull_request_target漏洞,拿到了 aqua-bot账号的写权限 PAT token。Aqua 做了修复,但……修得不够彻底。
3 月 19 日,残留的访问权限被利用了,TeamPCP 冒充维护者发布了带后门的 Trivy 二进制文件,劫持了 75 个 GitHub Actions 标签。后门直接从下游 CI/CD 流水线的 Runner 进程内存中刮取凭证。
3 月 20 日,用偷来的 npm token 部署了一个叫 CanisterWorm 的自我复制蠕虫,能自动枚举并发布恶意补丁到所有该 token 有权限访问的包。这个蠕虫用了 ICP(Internet Computer Protocol)作为 C2 通道,去中心化的,传统的域名封禁对它没用。
3 月 22-23 日,Checkmarx 的服务账号沦陷了,KICS GitHub Action 的全部 35 个标签被劫持,VS Code 插件市场也出现了带后门的插件。Kubernetes 持久化代码在这一阶段首次亮相。
3 月 24 日,昨天,轮到了 LiteLLM。而 LiteLLM 的 CI/CD 流水线恰好使用了 Trivy 做安全扫描,且没有锁定版本。被投毒的 Trivy 在流水线里执行时,直接从 GitHub Actions 的环境变量中偷走了 PYPI_PUBLISHtoken。
每一次攻击偷到的凭证,都成了下一次攻击的入场券。
而 TeamPCP 有个特别阴险的策略:专门挑安全工具下手。漏洞扫描器、代码分析器、LLM 代理……这些工具天生就要跑在高权限环境里,一旦被攻破,拿到的凭证质量极高。
用 Snyk 的话说:你的防守工具,变成了攻击你的武器。
SOC 2 废纸
这件事背后,还有个讽刺的插曲。
LiteLLM 在官网上标注了自己通过了 SOC 2 Type I 认证,而SOC 2 应该意味着一家公司的安全流程经过了独立审计。
但有人扒出来了:LiteLLM 的 SOC 2 是 Delve 签发的。
Delve,就是那个最近被曝出伪造了 533 份 SOC 2 审计报告的公司。
SOC 2 信任链断裂
9700 万月下载量,零真实审计。SOC 2 的牌子挂在那里,给了所有人一种「有人替你检查过了」的安全错觉。
瑞士 AI 教授 François Fleuret 质疑道:「Python 生态为什么不在各个层面都做加密签名呢?」
虽然有人回复说包已经签名了,但没用,因为发布者账号本身就被盗了。
签名验证的是「包确实是这个账号发的」,但验证不了「这个账号有没有被控制」。
认证验证的是流程,验证不了代码。合规不等于安全。
Agent 时代的新恐惧
Jim Fan 提出了一个比凭证盗窃更进一步的担忧:Agent 劫持。
窃取凭证太明显了,那是菜鸟做的事。它们完全可以把污染扩散到 ~/.claude、**/skills/*,甚至只是你的 Agent 定期读取的一个 PDF。
窃取凭证太明显了,那是菜鸟做的事。它们完全可以把污染扩散到 ~/.claude、**/skills/*,甚至只是你的 Agent 定期读取的一个 PDF。
想想看:如果恶意代码不去偷你的 SSH 密钥,而是悄悄修改你 Agent 的 skill 文件或者系统提示词呢?
Agent 劫持攻击路径
你的 AI Agent 可能就此变成别人的傀儡,用你的身份在所有接入的平台上操作,而你毫不知情。
他管这叫「de-vibing」:用严肃的、经过审计的 Software 1.0 来看管那些奔放的 Software 3.0。Agent 需要壳(shell),而且可能需要很多层嵌套的壳。
这个观察,其实指向了 AI Agent 安全的一个结构性缺陷:目前「逐项确认每次编辑」和「dangerously-skip-permissions」之间,几乎没有中间地带。
依赖是原罪?
Karpathy 最后写道:
传统软件工程会告诉你依赖是好事(我们在用砖头盖金字塔),但在我看来这个观念必须被重新审视了。这也是我为什么越来越抵触依赖,更倾向于用 LLM 来「yoink」功能:当功能足够简单且可行时,直接让 AI 帮你把代码写出来。
传统软件工程会告诉你依赖是好事(我们在用砖头盖金字塔),但在我看来这个观念必须被重新审视了。这也是我为什么越来越抵触依赖,更倾向于用 LLM 来「yoink」功能:当功能足够简单且可行时,直接让 AI 帮你把代码写出来。
怎么讲,「yoink」这个词,虽然挺有画面感的,但我感觉这是取名大师又要造新词了……
它的意思的是:与其 pip install一个库引入一整棵依赖树和它背后所有不可控的风险,不如让 LLM 直接把你需要的那几十行代码写出来,塞进你自己的项目里。
零依赖,零风险。
Lightning AI 的 Sebastian Raschka 也给了类似思路:
从 GitHub 拉源码快照,用 LLM 辅助做安全审计,然后把审计过的代码直接嵌入自己的项目。
从 GitHub 拉源码快照,用 LLM 辅助做安全审计,然后把审计过的代码直接嵌入自己的项目。
以前你自己写一个 HTTP 客户端、一个 JSON parser,成本太高了,所以依赖是合理的选择。
但现在呢?LLM 能在几秒钟内帮你生成这些代码,依赖的成本收益比,正在被彻底改写。
当然了,对 LiteLLM 这种复杂的多模型代理层来说,yoink 可能不太现实。
Jim Fan 也表示:
大多数人其实用不到 LiteLLM 支持的所有 API,不如按需搭建一个只包含你需要的模型的自定义路由。
大多数人其实用不到 LiteLLM 支持的所有 API,不如按需搭建一个只包含你需要的模型的自定义路由。
Karpathy 说的是:
我们构建的整个现代软件大厦,地基是信任。
而供应链攻击,动摇的恰恰就是这个地基。
怎么自查
如果你在 3 月 24 日前后安装或更新过 LiteLLM,或者安装过依赖 LiteLLM 的包(DSPy、CrewAI、MLflow 等),建议立刻检查:
# 检查是否存在恶意 .pth 文件find "$(python3 -c 'import site; print(site.getsitepackages[0])')"-name "litellm_init.pth"
# 检查持久化后门ls-la ~/.config/sysmon/sysmon.py systemctl --user status sysmon.service
# 检查 Kubernetes 中的可疑 Podkubectl get pods -A | grep node-setup
如果发现中招,需要:
删除后门文件和 sysmon 服务
检查 Kubernetes 集群是否有 node-setup-*的 Pod
审计 AWS Secrets Manager 和 SSM Parameter Store 的访问日志
然后,轮换所有凭证。是的,所有。SSH 密钥、云凭证、API Key、数据库密码、npm token……全部重新生成
删除后门文件和 sysmon 服务
检查 Kubernetes 集群是否有 node-setup-*的 Pod
审计 AWS Secrets Manager 和 SSM Parameter Store 的访问日志
然后,轮换所有凭证。是的,所有。SSH 密钥、云凭证、API Key、数据库密码、npm token……全部重新生成
目前 LiteLLM 在 PyPI 上已被隔离,恶意版本已删除。
官方建议回退到 v1.82.6 或更早版本。
LiteLLM 官方表示已聘请 Google Mandiant 进行取证分析,并暂停发布新版本,等待更广泛的供应链审查完成。
pip install 这四个字,从来都没有看起来那么无害。
而你的依赖树里藏着什么,
可能你自己也不知道。
广升网提示:文章来自网络,不代表本站观点。