开源依赖成为主战场:给软件供应链加上隔离、冷却与验证

2026-07-30 22 预计阅读时间: 1 分钟
来源: cloud.google.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:13 分钟

软件供应链攻击的重心正在发生变化。相比入侵大型软件厂商并篡改更新渠道,攻击者越来越多地盯上 npm、PyPI、Docker Hub、GitHub Actions 和开发者工具:接管维护者账号、投放恶意版本、利用安装脚本窃取凭据,再借助被盗令牌继续污染其他项目。

来源材料指出,2025 年至 2026 年上半年出现了一批规模显著扩大的开源供应链攻击,部分行动甚至使用蠕虫式传播和迭代入侵。OpenSSF 汇总的数据也显示,2025 年检测到的恶意开源软件包数量较 2024 年增长了 1,444%。面对这种攻击,单独部署一个漏洞扫描器远远不够,防线必须覆盖依赖进入、流水线执行、凭据使用、制品发布和事件响应的完整链路。

为什么开源仓库成了高收益入口

传统供应链攻击通常需要长期潜伏、掌握厂商构建系统,并精确操纵签名或更新基础设施。开源生态降低了这些门槛:一个被社会工程攻陷的维护者账号、一条权限过大的 GitHub Actions 工作流,或者一个无人维护但下载量可观的软件包,都可能成为入口。

这种攻击同时具备三个特点:

  • 传播效率高:热门包可能被成千上万个直接和间接依赖引用,恶意版本一旦进入自动更新流程,影响会迅速扩散。
  • 容易接触高价值凭据:安装过程经常运行在开发者电脑或 CI Runner 上,环境中可能存在云密钥、npm 发布令牌、GitHub Token 和代码签名材料。
  • 暴露后较为嘈杂:恶意包通常会被社区快速分析并下架,但几小时的窗口对高下载量依赖已经足够危险。

AI 编程工具又放大了这个问题。编码代理可以快速搜索和引入依赖,却未必能判断一个名称相似、刚刚发布或携带恶意 MCP 工具定义的软件包是否可信。攻击者同样可以利用 AI 批量生成仿冒包、钓鱼材料和针对不同生态的载荷。因此,AI 生成的依赖变更也必须经过与人工提交相同的审查和策略检查。

把依赖入口改成“内部仓库加冷却窗口”

有效的第一道门不是“发现恶意代码后报警”,而是让未经验证的新版本暂时无法进入构建环境。团队可以把公网仓库同步到内部制品库,在同步过程中执行恶意软件检测、许可证检查、漏洞扫描和发布时间冷却。

Node.js 项目可以这样实践。下面的 .npmrc 会锁定内部仓库、关闭生命周期脚本,并要求安装严格遵循锁文件。运行前请将 registry.example.com 替换为组织自己的 npm 代理地址:

registry=https://registry.example.com/repository/npm-group/
ignore-scripts=true
save-exact=true
package-lock=true

在 CI 中使用不可变安装,避免流水线临时解析出与审查时不同的版本:

set -euo pipefail
npm ci --ignore-scripts
npm audit --audit-level=high

使用 pnpm 的团队还可以在支持该能力的版本中设置最小发布时间,并仅允许经过确认的软件包执行构建脚本。具体字段支持情况应以当前 pnpm 版本为准:

# pnpm-workspace.yaml
minimumReleaseAge: 1440
onlyBuiltDependencies:
  - esbuild

1440 分钟意味着新版本至少等待 24 小时。冷却期不能证明软件包安全,但能为社区发现账号接管、恶意发布和异常安装脚本争取时间。旧版包管理器可能忽略相关配置,落地策略时必须把客户端最低版本检查加入 CI。

Python 项目同样不应允许构建机绕过组织策略直接访问公共 PyPI。可以这样配置 pip.conf

[global]
index-url = https://pypi.example.com/simple
trusted-host = pypi.example.com
require-virtualenv = true
disable-pip-version-check = true

随后使用哈希锁定依赖。下面假设 requirements.txt 已由组织批准的锁定工具生成,并包含每个制品的 --hash

python -m venv .venv
. .venv/bin/activate
python -m pip install --require-hashes -r requirements.txt

这里的关键不是某个配置项,而是建立唯一入口:开发机、CI 和生产镜像都只能从经过审查的内部仓库获取依赖。否则攻击者只需找到一条仍能直连公网的安装路径,就可以绕过冷却和隔离策略。

流水线要按不可信代码执行环境设计

依赖包和外部 Pull Request 都属于不可信输入。Runner 不应拥有长期存在的发布令牌,也不应与生产网络处在同一信任区域。

尤其需要审计 GitHub Actions 的 pull_request_target。该触发器在基础仓库上下文中运行,可能接触仓库密钥和写权限。如果工作流随后检出并执行外部贡献者的代码,攻击者就可能直接读取凭据。

处理普通外部贡献时,可以这样实践:使用权限较低的 pull_request,明确收紧默认权限,并禁止安装脚本:

name: pull-request-check

on:
  pull_request:

permissions:
  contents: read

jobs:
  test:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm
      - run: npm ci --ignore-scripts
      - run: npm test

如果业务确实需要 pull_request_target,不要在同一个高权限作业中检出或执行 PR 分支代码。把标签、评论等元数据操作与代码测试拆成独立工作流,并通过人工审批或经过验证的制品传递结果。

流水线身份也应从长期 PAT 转向 GitHub App 或 OIDC 短期凭据。云端角色只允许特定仓库、分支和工作流声明进行交换,令牌在几分钟后失效。配合一次性 Runner、最小网络出口和只读文件系统,即使恶意依赖成功执行,其可窃取的内容和可到达的系统也会明显减少。

用 SBOM、ABOM 和 OSV 扩大可见性

SBOM 回答“产品里有什么软件”,但供应链排查还需要回答“谁构建了它”。因此还应维护 ABOM,记录 GitHub Actions、第三方构建插件、CI 服务和开发工具,并把这些动作关联到最终容器镜像或发布制品。

可以在 CI 中加入 OSV-Scanner,对锁文件或源码目录中的依赖进行已知漏洞检查。安装方式和参数可能随版本演进,接入前应核对当前发布说明;一个基础流水线可以这样实践:

set -euo pipefail

osv-scanner scan source -r .
osv-scanner scan image "registry.example.com/team/app:${GIT_COMMIT}"

扫描结果不应被当作供应链安全的全部。OSV 擅长把已知漏洞映射到明确版本范围和提交,但它无法保证一个刚发布、尚未被报告的包没有恶意行为。更完整的准入流程还应包括:

  • 生成并集中保存 SBOM,持续与新披露漏洞交叉比对。
  • 校验制品哈希、数字签名和来源证明,构建过程逐步对齐 SLSA。
  • 在隔离沙箱中观察安装脚本、网络连接和文件写入行为。
  • 检查依赖维护者的恢复邮箱域名,识别已过期或可重新注册的域名。
  • 监控工作流修改、异常触发器、未知出口地址和长期密钥的异地使用。

落地顺序:先切断可串联的攻击链

供应链风险不应被拆成互不相关的告警。一次严重入侵往往由多个普通问题串联而成:锁文件可被绕过,Runner 拥有写权限,OIDC 信任条件过宽,同时生产网络允许任意出站连接。治理时应按攻击链排序,而不是只按单个漏洞的 CVSS 分数排序。

建议按以下顺序推进:

  1. 盘点应用、直接依赖、传递依赖、CI 动作、制品仓库和发布身份,建立 SBOM 与 ABOM。
  2. 强制所有包管理器使用内部仓库,启用新版本冷却、锁文件和哈希验证。
  3. 默认禁用 npm 生命周期脚本,只为必要且经过审查的包建立允许列表。
  4. 清理长期 PAT 和发布密钥,改用短期 OIDC 身份、GitHub App 与硬件保护的签名密钥。
  5. 审计 pull_request_targetrepository_dispatch 等高风险触发器,并将外部代码与高权限作业隔离。
  6. 使用一次性 Runner、严格出口白名单和生产网络分段限制恶意代码的影响范围。
  7. 为维护者账号接管、依赖混淆、流水线凭据收割和开发者工作站失陷分别演练响应流程。

平台原生安全默认值会持续变化,来源材料也提到了包管理器、Dependabot 与 PyPI 侧的进一步保护计划。团队不能预设这些能力已经覆盖所有环境;上线前应核对实际版本、托管平台文档和组织策略的生效结果。真正稳健的供应链防线依靠多层控制:延迟未经验证的变更、隔离不可信执行、缩短凭据寿命,并保留足够完整的证据来快速定位和撤回受污染制品。


相关推荐