LiteLLM PyPI 供应链攻击复盘:受影响版本、攻击方式与止损建议

本文复盘 2026 年 3 月 LiteLLM PyPI 供应链攻击事件,解释 1.82.7 与 1.82.8 的恶意植入方式、.pth 启动机制、可能泄露的敏感信息,以及团队应如何排查、止损与改进供应链防护。

2026 年 3 月 24 日,Andrej Karpathy 发帖提醒开发者关注 LiteLLM 的 PyPI 供应链攻击后,这起事件很快在 AI 和 Python 圈里扩散。它让人后背发凉,不只是因为受影响的包下载量不小,更因为这次恶意代码并不依赖“你真的运行了 LiteLLM 的业务逻辑”,而是有一个版本可以在 Python 启动时自动执行。

如果团队近期装过 litellm,这不是一个适合“等一等再看”的事件。下面按照公开资料把这次攻击的时间线、技术细节、影响范围和处置建议梳理一遍。

从 Karpathy 的提醒里,能看到这次事件真正危险的地方:只需要执行一次 pip install litellm,就可能导致 SSH key、云凭证、Kubernetes 配置、环境变量和其他高价值秘密被外传。这件事也不只是 LiteLLM 自己的问题,它更像是一次集中暴露,提醒大家重新认识 AI 时代被放大的依赖风险。原因并不复杂,如今的 AI 开发环境往往天然持有更多模型 API Key、云平台凭证、向量数据库连接、代码仓库权限和自动化工具密钥,一次依赖投毒造成的外溢影响,通常比传统应用环境更大。

受影响版本与风险边界

根据 LiteLLM 官方在 GitHub issue 里的说明,目前公开明确被确认遭到恶意植入的版本是 1.82.71.82.8。不过团队在后续更新里也提醒,其他版本同样应该纳入审计范围,因此不要把排查边界机械地收窄到这两个版本号上。

版本 恶意植入位置 触发方式 风险特征
1.82.7 litellm/proxy/proxy_server.py 导入相关模块时触发 需要走到特定导入路径
1.82.8 litellm_init.pth Python 启动时触发 不需要显式 import litellm

LiteLLM 团队在后续更新里明确写到,1.82.71.82.8 已经从 PyPI 删除;截至 2026 年 3 月 25 日,PyPI 项目页上显示的公开最新版本又变成了 1.82.6。这里特别强调日期,是因为很多人在社交媒体上看到的是“最新版本有毒”,但在真正排查时,PyPI 页面看到的“最新版本”可能已经变了。

1.82.8 的危险点在 .pth 自动执行

这次事件里,最值得所有 Python 开发者记住的一点是:安装包并不只是“放几个 .py 文件到 site-packages”

LiteLLM 官方说明指出,1.82.8 的 wheel 文件里包含了一个 litellm_init.pth。而 Python 官方文档对 .pth 的说明非常关键:如果 .pth 文件里有可执行行,那么它会在 每次 Python 启动时执行。这意味着攻击者不需要等你调用 LiteLLM,也不需要等你走到某个业务分支,只要这个环境启动了 Python,就可能触发恶意逻辑。

这也是为什么很多人把这次事件定义为“安装即中招”而不只是“运行某个功能才中招”。对 CI/CD、Agent 平台、Notebook 环境和本地开发机来说,这种差别非常大。

恶意代码盯上的敏感信息

根据最早公开的 LiteLLM 官方告警,恶意代码会尝试收集并外传一长串敏感信息,包括但不限于:

  • SSH 密钥
  • AWS、GCP、Azure 凭证
  • Kubernetes 配置
  • Git 凭证
  • 环境变量中的 API Key
  • Shell 历史
  • 加密钱包
  • SSL 私钥
  • CI/CD Secrets
  • 数据库相关敏感信息

官方 issue 里还提到,恶意代码将数据发送到 https://models[.]litellm[.]cloud/。LiteLLM 团队特别提醒,这个域名并不是他们的官方域名 litellm.ai

换句话说,如果受影响环境里正好带着云账户、私钥、数据库密码或者 GitHub Token,那么真正的风险不是“这个虚拟环境脏了”,而是整条信任链都可能已经被穿透

攻击入口指向 PyPI 发布链路

LiteLLM 团队在 2026 年 3 月 24 日的说明中表示,他们确认攻击者是直接向 PyPI 上传了恶意版本,而不是通过 LiteLLM 的 GitHub Actions、代码仓库 PR 或 release 流程投毒。团队随后删除了恶意版本、轮换了维护者账号访问权限,并表示已联系 Mandiant 介入调查。

这一点很重要,因为它提醒所有开源用户:即使 GitHub 仓库看起来干净,也不能自动推断 PyPI 上的构建产物就一定干净。对开源用户来说,包仓库发布链路本身就是攻击面

Trivy 线索与当前能确认的边界

截至 2026 年 3 月 25 日,公开信息已经显示出较强的关联迹象,但还不足以把它写成已经被完整坐实的直接因果关系。

目前公开信息里已经有两条能够对上的线索。第一,LiteLLM 官方在后续 issue 更新中写到,Compromise came from trivvy security scan dependency。第二,Aqua 和 GitHub 在 2026 年 2 月 18 日到 2 月 19 日 曾公开披露过 aquasecurity/trivy-action 的安全问题,官方公告说明该问题在特定条件下可能导致 GitHub Actions runner 上的任意命令执行。

但另一方面,现阶段公开材料里仍然缺少最后一跳证据。Aqua 的官方公告并没有点名 LiteLLM 是这次 Trivy 相关问题的下游受害者;LiteLLM 官方 issue 也没有完整展开说明这里的 trivvy security scan dependency 到底具体指向哪个组件、哪个版本,以及攻击链条是否就是从该依赖一路走到 PyPI 维护权限泄露。

综合现有公开资料,更稳妥的判断是:LiteLLM 官方已经给出了与 Trivy 相关依赖有关的线索,而结合此前 trivy-action 的官方安全披露,二者存在明显关联的可能性。

需要立刻排查的环境

如果符合下面任意一种情况,建议把这件事按高优先级安全事件处理:

  • 你在 2026 年 3 月 24 日到 2026 年 3 月 25 日这段时间内执行过 pip install litellm,或者在这段时间拉取过“最新版本”
  • 你的 CI job、Agent runner 或容器镜像在这段时间内安装过 litellm
  • 你的环境里保存过云凭证、SSH key、Kubernetes 配置、生产数据库密码或大量 API Key
  • 你的团队有人使用共享基础镜像,或者把 Python 虚拟环境打进了可复用构建缓存

LiteLLM 官方也提到,使用他们官方 Proxy Docker image 的用户不受这次事件影响,因为对应镜像依赖并没有拉到受污染版本。但如果你不是走官方镜像,而是自己在 Dockerfile、CI 脚本、开发机或 Agent 环境里 pip install litellm,那就不在这个保护范围里。

AI 时代为何更容易放大依赖风险

如果只把这起事件理解成“某个 Python 包出事了”,很容易低估它真正的危险性。Karpathy 的提醒之所以会迅速传播,本质上正是因为它击中了 AI 开发的一个结构性问题:现代 AI 工作流把太多高权限秘密集中到了同一个运行环境里

一个典型的 AI 工程环境,往往同时包含下面这些内容:

  • 多家模型服务商的 API Key
  • 云平台访问凭证
  • 向量数据库连接信息
  • GitHub 或 GitLab Token
  • Kubernetes 配置
  • 内部工具或自动化平台密钥

这意味着在 AI 时代,依赖供应链攻击带来的问题已经不再只是“本地开发环境被污染”,而更接近“一个安装动作撬动整套生产能力”。也正因为如此,这类事件不能只交给单个开发者临时处置,而应该进入团队层面的依赖治理、凭证治理和发布治理流程。

处置建议:重点不是卸载,而是止损

如果确认安装过 1.82.71.82.8,建议默认按“凭证已泄露”处理,而不是按“也许没事”处理。

1. 先确认影响面

先检查哪些机器、容器、CI 任务、Notebook、Runner 安装过受影响版本:

python -m pip freeze | grep -i '^litellm=='
pip show litellm

如果你要进一步定位 .pth 文件,可以先找出当前环境的 site-packages 路径:

python - <<'PY'
import site
paths = []
try:
    paths.extend(site.getsitepackages())
except Exception:
    pass
paths.append(site.getusersitepackages())
for p in paths:
    print(p)
PY

然后查找是否存在可疑文件:

find /path/to/site-packages -name 'litellm_init.pth'

2. 立刻轮换凭证

如果环境里有下面这些内容,请优先轮换:

  • 云平台访问密钥
  • GitHub、GitLab、CI Token
  • 数据库密码
  • API Keys
  • Kubernetes Secret 或 kubeconfig
  • SSH 密钥
  • TLS/SSL 私钥

这里最容易犯的错误是“先把包卸了再说”。如果凭证已经外传,卸载包并不会把风险收回去。

3. 重建环境,而不是原地修修补补

对容器、CI Runner 和开发环境来说,更稳妥的做法通常是:

  • 删除受影响虚拟环境或镜像层缓存
  • 从可信基础镜像或干净机器重新构建
  • 重新注入已经轮换过的新凭证

如果你只是把 litellm 卸载掉,但继续复用旧缓存、旧镜像层或旧凭证,那很容易留下二次风险。

把 Trivy 放进补充排查流程

如果团队已经在安全流程里使用 Trivy,这次排查完全可以把它作为补充分析工具接进来。根据 Trivy 官方文档,trivy fs 可以扫描本地文件系统中的 漏洞、错误配置、Secrets 和许可证,默认启用漏洞与 Secret 扫描;trivy image 则可以对容器镜像做同类扫描。

对 LiteLLM 这类供应链事件来说,Trivy 最有价值的用途通常有三类:

  • 扫描项目目录或锁文件,确认依赖清单与已知风险
  • 扫描虚拟环境、构建上下文或容器镜像,查找意外暴露的 Secrets
  • 生成 SBOM,方便后续审计、共享和二次扫描

不过这里有一个边界必须说清楚:Trivy 检测的是已知漏洞和已知问题,而不是“所有恶意包行为”。Trivy 官方文档明确写到,它识别的是软件组件中的 known vulnerabilities。对 Python 生态来说,Trivy 主要依赖公开的 advisory 数据来判断风险。因此,如果某个恶意版本还没有被及时写入相应漏洞或公告数据库,Trivy 没有报红,并不等于这个依赖没有被投毒。

1. 扫描项目目录或锁文件

如果想先快速确认项目依赖和秘密暴露情况,可以直接扫描代码目录:

trivy fs --scanners vuln,secret .

Trivy 官方文档还提到,fs 扫描可以直接针对单个文件运行,因此像 requirements.txtPipfile.lockpoetry.lock 这类 Python 依赖文件都可以单独扫描。对于 Python 包本身,Trivy 文档也列出了 wheelegg 支持。

如果排查入口是 requirements.txt,还要注意一个细节:Trivy 官方文档指出,requirements.txt 通常只包含直接依赖,因此默认只能覆盖直接依赖。想把传递依赖也纳入排查,最好先在目标环境中执行一次 pip freeze,再让 Trivy 扫描生成后的依赖清单。

2. 扫描 Python 虚拟环境

如果怀疑问题出在某个已经安装过依赖的虚拟环境,更实用的方式通常是直接扫描这个环境目录:

trivy fs --scanners vuln,secret /path/to/venv

这样做的好处是,不只看源码仓库里声明了什么,还能看当前环境里实际装进去了什么。对排查“CI 机器是不是曾经装过有问题版本”这类问题尤其有帮助。

3. 扫描受影响镜像

如果风险来自 CI Runner、Agent 容器或基础镜像,建议把镜像也纳入排查:

trivy image your-runner-or-agent-image:tag

Trivy 官方文档说明,image 扫描默认同样会做漏洞和 Secret 扫描。这对于检查构建镜像里是否还残留旧依赖、旧凭证或其他可疑内容很有价值。

4. 生成 SBOM 做后续审计

如果需要把这次排查沉淀成可共享的清单,Trivy 也可以直接生成 CycloneDX SBOM:

trivy fs --format cyclonedx --output trivy-sbom.json .

随后可以继续用 Trivy 对这个 SBOM 做二次扫描:

trivy sbom trivy-sbom.json

官方文档特别提醒,--format cyclonedx 默认用于生成 SBOM,本身不会自动把漏洞结果写进 CycloneDX 输出。如果想在 CycloneDX 输出里同时带上漏洞信息,需要显式指定 --scanners vuln

5. 把 Trivy 放在正确的位置

在这类事件里,引入 Trivy 的意义并不在于它能“自动识别 LiteLLM 这次恶意代码的全部行为”,而是因为它很适合承担下面这些补充工作:

  • 快速梳理当前项目、虚拟环境和镜像里的依赖面
  • 尽快发现明文 Secrets 或其他不该出现在环境里的敏感内容
  • 产出 SBOM,方便团队后续追踪受影响资产

但它不能替代凭证轮换、环境重建和发布链路审计。对这类供应链攻击,Trivy 更像是一个很有价值的辅助分析工具,而不是唯一判断依据。

这次事件留给 Python 团队的提醒

1. pip install 本质上也是执行代码

很多团队把“安装依赖”当成一个无害动作,但这次事件再次说明,安装链路和运行链路之间并没有想象中那么清晰的边界。.pthsitecustomize、安装脚本、入口点生成,这些都可能成为执行面。

2. 版本锁定不够,最好连哈希也锁

只写 litellm>=1.82 这种宽范围约束,在供应链事故里基本等于裸奔。更稳妥的做法是:

  • 锁精确版本
  • pipuvpip-tools 里启用哈希校验
  • 对关键依赖建立内部镜像或审计缓冲区

3. 要把“新版本隔离观察”做成流程

高频依赖一有新版本就自动进生产,是非常危险的默认设置。对 AI 基础设施这类高权限环境,更稳妥的方式通常是:

  • 先在隔离环境安装
  • 跑静态扫描和最小化行为检查
  • 再进入共享镜像和 CI 模板

4. CI 尽量使用短期、最小权限凭证

这次攻击之所以杀伤力大,是因为很多开发和 CI 环境天然就持有太多高价值秘密。即使不能完全阻止包仓库投毒,至少也要降低“被偷一次就横向拿下全公司”的可能性。

写在最后

LiteLLM 这次事故最值得警惕的地方,不只是某个流行包被投毒,而是它精准命中了今天最敏感的一类环境:AI 开发机、Agent 容器、云函数、CI/CD 和带大量 API Key 的 Python 工作流。

很多团队已经习惯把大模型接入、云凭证、向量数据库、代码仓库访问权限都放进同一个开发环境里。这样的环境一旦被供应链攻击命中,后果往往不会停留在“一个 Python 包出了问题”,而是直接升级成跨系统凭证泄露事件。

如果说这次事件有什么值得所有团队立即调整的地方,那就是:把依赖安装当作高风险动作来治理,而不是把它当成一条不起眼的初始化命令。

参考资料

使用 Hugo 构建
主题 StackJimmy 设计