在现代软件工程的协同开发范式下,第三方库已成为构建复杂系统的基石。然而,这种深度依赖也使得软件供应链成为攻击者渗透企业核心基础设施的首选路径。2026年3月发生的 LiteLLM 投毒事件不仅是一次单纯的恶意代码注入,更是针对开发者工具链的一次精确打击。通过对该事件的深度解构,并结合 Rust、Go 和 Zig 等现代编程语言在包管理设计上的差异性分析,可以清晰地观察到包管理哲学正从单一的“信任模型”向“验证与分布式协同”的范式演进。本文旨在通过对 LiteLLM 事件的复盘,探讨 Rust 包管理器的技术特征,并对比中心化与分布式包管理架构在应对此类威胁时的优劣。

LiteLLM 供应链攻击深度解构:TeamPCP 的第九阶段行动
2026年3月24日,威胁参与者 TeamPCP 成功在 Python 包索引(PyPI)上发布了 litellm 的两个恶意版本:1.82.7 和 1.82.8 1。这次攻击并非孤立的账户劫持,而是 TeamPCP 代号为“Phase 09”的系列行动,其核心策略在于“攻击安全工具以获取后续权限” 1。LiteLLM 作为连接百余种大语言模型(LLM)提供商的网关工具,日下载量高达340万次,且通常持有大量云服务提供商、数据库以及 AI 模型提供商的敏感 API 密钥,这使其成为了攻击者眼中的高价值目标 1。
攻击链的起源:安全扫描器的反噬
此次攻击的源头可以追溯到2026年2月后期,当时攻击者利用了 Trivy 这一流行开源安全扫描器 CI/CD 流程中的 pull_request_target 工作流漏洞,成功窃取了名为 aqua-bot 的凭据 1。Trivy 在行业内通常被赋予较高的执行权限,以完成镜像扫描和漏洞检测任务。3月19日,攻击者进一步通过重写 Git 标签,将 trivy-action 的 GitHub Action 指向了恶意的 v0.69.4 版本 1。
3月24日,LiteLLM 的 CI/CD 流程在构建过程中调用了未经版本锁定的 Trivy 扫描器。由于该流水线直接从 apt 源拉取扫描器且未指定特定的版本哈希,恶意的扫描动作在执行时直接从 GitHub Actions 的运行环境(Runner Environment)中提取了 PYPI_PUBLISH 令牌 1。随后,攻击者利用这一合法令牌,绕过了项目标准的 GitHub 发布工作流,直接向 PyPI 上传了包含后门的安装包 4。
恶意负载的技术机制:从代码注入到.pth 隐蔽执行
攻击者在 1.82.7 和 1.82.8 两个版本中采用了不同的代码注入策略,反映了其对 Python 解释器运行机制的深入理解。1.82.7 版本通过在 litellm/proxy/proxy_server.py 中嵌入 Base64 编码的负载进行源代码注入,而 1.82.8 版本则引入了更具威胁的 .pth 文件机制 1。
| 恶意版本 | 注入方式 | 执行触发条件 | 隐蔽性与威胁程度 |
|---|---|---|---|
| v1.82.7 | 源代码注入 | 开发者显式导入 litellm.proxy 时触发 1 | 较低,仅在特定功能模块被调用时执行。 |
| v1.82.8 | .pth 文件注入 | Python 解释器启动时自动执行,无需显式导入 1 | 极高,任何调用 Python 的操作(如 pip 或 IDE 插件)均会激活负载。 |
.pth 文件(路径配置文件)本意是用于向 Python 搜索路径添加目录,但其支持执行代码的特性使其成为了攻击者的完美温床。由于 Python 解释器在启动阶段会遍历 site-packages 中的所有 .pth 文件并执行其中的代码,这意味着即使开发者仅仅是运行 pip show litellm 来检查版本,恶意逻辑也会在后台悄然启动 1。这种“启动即感染”的特性导致了意外的“分叉炸弹”(Fork Bomb)效应,使得部分受感染机器因进程过度生成而死机,这也是该漏洞最早被研究人员发现的原因之一 1。
三阶段攻击负载与数据窃取逻辑
一旦恶意逻辑被激活,它会按照 TeamPCP 预设的三个阶段执行其任务,表现出极强的侦察与持久化能力:
- 第一阶段:全面侦察与凭据收割:负载会扫描受感染系统的环境变量、.ssh/ 目录下的私钥、AWS/GCP/Azure 的云服务配置文件、Kubernetes 的 kubeconfig 以及加密货币钱包助记词 2。
- 第二阶段:加密外传:收割的数据被打包为 tpcp.tar.gz,采用 AES-256-CBC 算法加密。攻击者生成了一个随机的 32 字节 AES 会话密钥,并使用硬编码的 4096 位 RSA 公钥对其进行加密,最后通过 curl 外传至仿冒域名 models.litellm.cloud 1。
- 第三阶段:持久化与横向移动:恶意软件会在 ~/.config/sysmon/ 目录下安装后门,并创建一个名为 sysmon.service 的 systemd 用户服务以确保在重启后依然存活 1。若检测到当前环境位于 Kubernetes 集群内,它还会尝试部署一个 DaemonSet(node-setup),以获取集群范围内的服务账号令牌和机密信息 1。
Rust Cargo:集中式注册表下的完整性博弈
面对类似 LiteLLM 这样的供应链威胁,Rust 语言及其包管理器 Cargo 展现出了一套完全不同的防御哲学。Cargo 并非仅仅是一个下载工具,它与 Rust 编译器及 crates.io 注册表深度整合,形成了一个以哈希校验和语义化版本(SemVer)为核心的防御体系 7。
模块、包与工作区的层级安全结构
Rust 的代码组织遵循严格的层级:模块(Module)构成包(Crate),而包可以组合成工作区(Workspace) 9。在 Cargo 的设计中,包是编译的基本单位,且每个包都必须通过 Cargo.toml 明确声明其外部依赖 9。与 Python 不同,Rust 的模块系统是静态的,这意味着编译器在构建时就锁定了代码的拓扑结构,不存在类似 .pth 文件这样可以在运行时动态修改代码搜索路径并执行额外逻辑的黑盒机制 9。
在工作区(Workspace)层面,所有成员共用一个 Cargo.lock 文件 9。这一设计确保了即使在一个包含数十个微服务的复杂项目中,所有组件所引用的第三方库版本也是完全一致的,极大地降低了由于依赖项版本漂移带来的安全风险 10。
完整性校验与 Cargo.lock 的确定性
Cargo 解决供应链篡改的核心武器是多重哈希校验机制。当开发者在 Cargo.toml 中添加一个依赖项时,Cargo 会执行以下完整性检查流程:
- 注册表哈希验证:Cargo 会从 crates.io 的索引中获取该版本包的 SHA-256 校验和 12。
- 确定性锁定:首次下载后,该校验和会被记录在 Cargo.lock 文件中 10。对于应用程序(Binary projects),官方强烈建议将 Cargo.lock 纳入版本控制,以确保 CI/CD 环境与开发环境构建出完全一致的二进制产物 10。
- 源代码级指纹:每个提取后的包目录中都包含一个 .cargo-checksum.json 文件,用于校验目录内每一个源代码文件的哈希值。任何对第三方库源码的本地修改都会导致 Cargo 在编译前报错,从而拦截了潜在的本地投毒尝试 13。
然而,LiteLLM 事件揭示了一个残酷的现实:即使有完善的哈希校验,如果上游维护者的账号被窃取,且恶意代码作为“合法版本”发布,校验和机制依然会认为该包是安全的 1。针对这一局限,Rust 社区正在推进“受信任发布”(Trusted Publishing)机制,利用 OIDC 令牌代替长期有效的 API 密钥,以降低令牌泄漏带来的风险 14。
build.rs:Rust 生态中的安全软肋
虽然 Rust 在运行时相对安全,但其构建系统中的 build.rs(构建脚本)机制引入了类似于 Python 安装脚本的安全风险。build.rs 允许在编译包之前执行任意 Rust 代码,常用于连接 C 库或生成代码 16。
由于 build.rs 以执行编译的用户权限运行,且拥有对网络和文件系统的完整访问权,它实际上成为了攻击者的理想跳板 16。在受限环境或涉及敏感密钥(如代码签名密钥)的构建任务中,恶意依赖项的 build.rs 完全可以像 LiteLLM 负载一样窃取环境变量或注入恶意二进制逻辑 18。目前的缓解措施主要依赖于 cargo-audit 等工具对已知漏洞的扫描,以及通过 config.toml 强制覆盖或禁用特定包的构建脚本执行 16。
分布式与中心化:包管理哲学的二元对立
LiteLLM 事件引发了关于包管理架构设计的大讨论:是以 PyPI、crates.io 为代表的中心化模型更安全,还是以 Zig 为代表的去中心化模型更具韧性?
中心化注册表的优势与单点崩溃风险
中心化注册表(Centralized Registry)如 PyPI 和 NPM,提供了统一的发现机制和元数据管理 20。
- 安全防御优势:注册表可以实施全局性的安全扫描。例如,crates.io 引入的“Security”选项卡直接展示了来自 RustSec 的漏洞预警,允许开发者在引入依赖前评估风险 14。一旦发现投毒包,注册表管理员可以迅速执行“隔离”或“撤回”操作,切断攻击路径 1。
- 攻击聚合风险:中心化节点是攻击者的高价值目标。一旦注册表的凭据管理系统或 CI 流程被突破,影响将是指数级的 2。LiteLLM 事件中,攻击者只需获取一个 PyPI 令牌即可影响数百万用户,这种效能放大效应是中心化系统的固有缺陷 2。
Zig:分布式内容寻址的探索
Zig 语言在 0.11 版本中引入了内置的包管理器,其设计哲学极度趋向于去中心化。Zig 不设官方中心仓库,而是直接从 URL(通常是 GitHub 的 tarball)拉取包 24。
在 Zig 的 build.zig.zon 清单文件中,包的标识符是其内容哈希值,而非名称。URL 被视为该哈希内容的“镜像”之一 25。这种“内容寻址”机制意味着,即使攻击者篡改了 GitHub 上的代码仓库,只要哈希值不匹配,Zig 构建系统就会拒绝使用该包 26。
| 特性 | 集中式 (crates.io/PyPI) | 分布式 (Zig) |
|---|---|---|
| 可发现性 | 极佳,提供搜索与排名 27 | 较差,依赖社区索引 24 |
| 可用性风险 | 注册表下线导致构建失败 20 | 特定 URL 失效可能中断构建 25 |
| 安全审计 | 中心化扫描与撤回机制 22 | 依赖开发者对特定哈希的审计 24 |
| 管理主体 | 企业或非营利基金会 20 | 社区驱动,无绝对权威 24 |
然而,去中心化也带来了“M x N”集成问题。由于缺乏统一的元数据标准和 PURL(包 URL)类型,Zig 难以接入现有的 SBOM(软件物料清单)生成工具和自动化漏洞数据库 24。此外,Zig 早期版本中“所有传递依赖必须在顶层清单声明”的要求,虽然在 0.12 版本中有所缓解,但依然体现了去中心化在处理大规模依赖拓扑时的复杂性 29。
跨语言生态实现对比:Go, Zig 与传统架构
在中心化与分布式的光谱上,Go 语言提供了一个极具参考价值的折中方案。
Go Modules 的混合防御架构
Go 最初也采用完全去中心化的方式,但为了解决“左垫片”(Left-pad)式的可用性危机和安全校验问题,Google 引入了 Proxy 和 SumDB(校验和数据库)架构 31。
- GOPROXY 的不可变性:一旦某个版本的模块被缓存到 proxy.golang.org,它就是不可变的。这防止了攻击者在删除旧版本后重新发布相同版本号的恶意代码 32。
- SumDB 的透明日志:Go 的校验和数据库采用了类似于区块链的 Merkle Tree 结构。这是一个追加、透明且可验证的日志系统 33。当开发者下载包时,Go 工具链会从 SumDB 获取该版本的全局校验和,确保全世界用户看到的源码完全一致。这种设计使得即使是代理服务器被攻破,也无法在不破坏 Merkle Tree 完整性的情况下伪造校验和 33。
安全性设计的核心差异:构建与执行
Go 语言在包管理上的一个关键安全目标是“构建过程不执行代码”。与 Rust 的 build.rs 或 Python 的安装脚本不同,Go 明确禁止在获取或构建依赖项时运行任何外部逻辑 33。这种策略极大地压缩了攻击面,使得类似 LiteLLM 这样通过安装脚本窃取凭据的手段在 Go 生态中几乎无法立足 33。
| 语言 | 默认校验机制 | 构建时执行代码 | 依赖解析策略 |
|---|---|---|---|
| Rust | Cargo.lock + 注册表哈希 10 | 是 (build.rs) 16 | 语义化版本解析 11 |
| Go | go.sum + SumDB 透明日志 34 | 否 33 | 最小版本选择 (MVS) 31 |
| Zig | build.zig.zon 内容哈希 26 | 是 (build.zig) 36 | 精确版本/哈希匹配 30 |
| Java | PGP 数字签名 (Maven) 37 | 否 (通常) 38 | 声明式版本解析 38 |
Maven Central:基于 PGP 签名的信任背书
Java 生态的 Maven Central 则走了一条“重流程”的道路。它强制要求所有发布的构件必须经过 PGP 签名 37。这意味着攻击者即便窃取了 Sonatype 平台的发布账号,如果无法同时控制维护者的 PGP 私钥,依然无法通过签名验证 37。虽然这种做法被批评为操作复杂,但它在防御“身份冒用”类供应链攻击方面提供了最强的身份保证 21。
深度洞察:供应链安全的未来演进趋势
通过对 LiteLLM 事件及各包管理系统的横向对比,可以推断出未来软件供应链安全的几个关键演进方向。
从哈希校验到透明日志的范式转移
单纯的本地哈希(如 Cargo.lock)只能保证开发者在某次确定性构建中不被干扰,但无法识别上游注册表的恶意更新。Go SumDB 所代表的“透明日志”模型正在被其他生态系统采纳。通过建立公开、可审计的发布流水线,包管理器可以确保任何版本的发布都是可追溯且不可篡改的。Sigstore 等技术的普及,预示着未来所有包管理注册表都将具备类似的公共审计能力。
自动化安全围栏的左移
LiteLLM 事件中,Snyk 和 Sonatype 等工具在攻击发生后的数小时内就发出了警报,并建议用户固定版本 1。这种实时防御能力依赖于包管理器与安全数据库的深度集成。Rust 在 crates.io 界面直接展示漏洞数据,以及 Go 编译器原生支持漏洞扫描(govulncheck),都标志着安全已不再是编译后的附件,而是开发工作流的首选项。
应对 AI 基础设施的安全特权化
LiteLLM 投毒事件暴露出 AI 基础设施的一个核心痛点:API 凭据的高度集中。由于 LiteLLM 作为一个集中网关处理了大量的秘密,其安全性收益与风险不成正比 2。未来的 AI 库设计可能会倾向于更细粒度的权限控制(如能力模型 Cap-and-Lock),或者采用专门的秘密管理集成(如直接与 HashiCorp Vault 通信),以避免秘密在环境变量中以明文形式暴露。
数字主权与协议层标准化
Zig 社区提出的“包管理协议”(DLP)旨在解决包管理器之间的互操作性问题 24。在数字化主权日益重要的今天,企业和国家机构越来越倾向于运行自己的私有注册表或透明代理。如果能实现一套跨语言的、基于 LSP 哲学的包管理协议,将能大幅提升全球范围内应对突发投毒事件的协同效率,使漏洞通报和补丁分发能够跨越生态边界。
结论
LiteLLM 投毒事件是软件供应链安全史上的一个分水岭,它证明了即便拥有成熟 CI/CD 和注册表防御体系的项目,也可能因上游微小的配置疏忽(如未锁定的扫描器版本)而导致全局崩溃。Rust Cargo 通过严格的哈希校验和 Cargo.lock 提供了坚实的本地防线,但在防御恶意上游发布时仍需结合 Trusted Publishing 等新机制。相比之下,Go 凭借不可变的 Proxy 和透明的 SumDB 架构,在中心化与分布式的博弈中找到了一个兼顾可用性与安全性的平衡点。
对于开发者而言,没有任何一种语言或工具能提供绝对的安全。安全防线的建立不仅依赖于选择具备先进完整性校验能力的包管理器,更依赖于对依赖规模的克制、对构建环境的隔离以及对异常行为的实时监控。在 AI 驱动开发的下半场,包管理器将不再仅仅是一个下载器,而将进化为整个软件生命周期的安全守门人。
Works cited
- How a Poisoned Security Scanner Became the Key to Backdooring LiteLLM | Snyk, accessed March 26, 2026, https://snyk.io/articles/poisoned-security-scanner-backdooring-litellm/
- The LiteLLM Supply Chain Attack: A Complete Technical Breakdown of What Happened, Who Is Affected, and What Comes Next - Blog, accessed March 26, 2026, https://blog.dreamfactory.com/the-litellm-supply-chain-attack-a-complete-technical-breakdown-of-what-happened-who-is-affected-and-what-comes-next
- Resources - Snyk, accessed March 26, 2026, https://snyk.io/resource-library/
- Security Update: Suspected Supply Chain Incident - LiteLLM, accessed March 26, 2026, https://docs.litellm.ai/blog/security-update-march-2026
- Embedded Malicious Code Affecting litellm package, versions [1.82.7][1.82.8] - Snyk Vulnerability Database, accessed March 26, 2026, https://security.snyk.io/vuln/SNYK-PYTHON-LITELLM-15762713
- Compromised litellm PyPI Package Delivers Multi-Stage Credential Stealer - Sonatype, accessed March 26, 2026, https://www.sonatype.com/blog/compromised-litellm-pypi-package-delivers-multi-stage-credential-stealer
- How to Use Cargo for Rust Project Management - OneUptime, accessed March 26, 2026, https://oneuptime.com/blog/post/2026-01-26-rust-cargo-project-management/view
- Introduction - The Cargo Book - Rust Documentation, accessed March 26, 2026, https://doc.rust-lang.org/cargo/
- Rust Module System Encourages Poor Practices (Comparing to Go) - Dmitry Frank, accessed March 26, 2026, https://dmitryfrank.com/articles/rust_module_system_encourages_bad_practices
- Registries - The Cargo Book, accessed March 26, 2026, https://doc.rust-lang.org/cargo/reference/registries.html
- Continuous Integration - The Cargo Book - Rust Documentation, accessed March 26, 2026, https://doc.rust-lang.org/cargo/guide/continuous-integration.html
- Registry Index - The Cargo Book - Rust Documentation, accessed March 26, 2026, https://doc.rust-lang.org/cargo/reference/registry-index.html
- Checksum in cargo::sources::directory - Rust, accessed March 26, 2026, https://doc.rust-lang.org/beta/nightly-rustc/cargo/sources/directory/struct.Checksum.html
- crates.io: development update - Rust Blog, accessed March 26, 2026, https://blog.rust-lang.org/2026/01/21/crates-io-development-update/
- Rust package registry adds security tools and metrics to crates.io, accessed March 26, 2026, https://www.helpnetsecurity.com/2026/01/21/rust-crates-io-security-update/
- Build Scripts - The Cargo Book, accessed March 26, 2026, https://doc.rust-lang.org/cargo/reference/build-scripts.html
- Building BlockSecOps: Why We Used Both Python and Rust | by Dehvcurtis | Medium, accessed March 26, 2026, https://medium.com/@dehvcurtis/building-blocksecops-why-we-used-both-python-and-rust-c2b1d3d4db4f
- Security of build.rs files : r/rust - Reddit, accessed March 26, 2026, https://www.reddit.com/r/rust/comments/1bz3lif/security_of_buildrs_files/
- Advisories › RustSec Advisory Database, accessed March 26, 2026, https://rustsec.org/advisories/
- Decentralized code distribution for the future of open source | by Andrew Hill | Textile, accessed March 26, 2026, https://medium.com/textileio/decentralized-code-distribution-for-the-future-of-open-source-2dc58f1153b2
- [AskJS] what makes NPM less secure than other package providers? : r/javascript - Reddit, accessed March 26, 2026, https://www.reddit.com/r/javascript/comments/1nkw6gr/askjs_what_makes_npm_less_secure_than_other/
- Rust RFC Proposes a Security Tab on crates.io for RustSec Advisories - Socket.dev, accessed March 26, 2026, https://socket.dev/blog/rust-rfc-proposes-a-security-tab-on-crates-io-for-rustsec-advisories
- Surfacing Security Advisories on crates.io: Bringing Vulnerability Data to the Point of Discovery - Alpha Omega, accessed March 26, 2026, https://alpha-omega.dev/blog/surfacing-security-advisories-on-crates-io-bringing-vulnerability-data-to-the-point-of-discovery/
- Zig and the M×N Supply Chain Problem - Andrew Nesbitt, accessed March 26, 2026, https://nesbitt.io/2026/01/29/zig-and-the-mxn-supply-chain-problem.html
- Dependencies proxy - Brainstorming - Ziggit, accessed March 26, 2026, https://ziggit.dev/t/dependencies-proxy/12996
- zig/doc/build.zig.zon.md at master · ziglang/zig · GitHub, accessed March 26, 2026, https://github.com/ziglang/zig/blob/master/doc/build.zig.zon.md
- What is the situation around package management works in zig? - Reddit, accessed March 26, 2026, https://www.reddit.com/r/Zig/comments/1pljhyb/what_is_the_situation_around_package_management/
- Playing with Zig and thinking about its package manager - Reddit, accessed March 26, 2026, https://www.reddit.com/r/Zig/comments/1cqunml/playing_with_zig_and_thinking_about_its_package/
- package manager: transitive dependencies must be listed in the top-level build.zig.zon is painful #17135 - GitHub, accessed March 26, 2026, https://github.com/ziglang/zig/issues/17135
- Injecting the right version of a transitive package dependency? - Help - Ziggit, accessed March 26, 2026, https://ziggit.dev/t/injecting-the-right-version-of-a-transitive-package-dependency/12036
- Deep Dive into Go Modules Dependency Management - Leapcell, accessed March 26, 2026, https://leapcell.io/blog/deep-dive-into-go-modules-dependency-management
- Why you should use a Go module proxy - Fatih Arslan, accessed March 26, 2026, https://arslan.io/2019/08/02/why-you-should-use-a-go-module-proxy/
- How Go Mitigates Supply Chain Attacks - The Go Programming Language, accessed March 26, 2026, https://go.dev/blog/supply-chain
- Demystifying Go proxy and Checksum Database - Byte Increments, accessed March 26, 2026, https://byteincrements.com/2025/07/29/demystifying-go-proxy-and-checksum-database/
- Does Go provide any security features to help prevent supply chain attacks? : r/golang, accessed March 26, 2026, https://www.reddit.com/r/golang/comments/1njkkev/does_go_provide_any_security_features_to_help/
- Zig Build System - Zig Programming Language, accessed March 26, 2026, https://ziglang.org/learn/build-system/
- Working with PGP Signatures - Documentation - Central Repository, accessed March 26, 2026, https://central.sonatype.org/publish/requirements/gpg/
- Is Maven similar to npm? - java - Stack Overflow, accessed March 26, 2026, https://stackoverflow.com/questions/38388824/is-maven-similar-to-npm
- Guide to uploading artifacts to the Central Repository - Apache Maven, accessed March 26, 2026, https://maven.apache.org/repository/guide-central-repository-upload.html
- Developer Guide for publishing to maven | Feathr, accessed March 26, 2026, https://feathr-ai.github.io/feathr/dev_guide/publish_to_maven.html