Hotdry.
systems-engineering

GitHub Actions 内建包管理器的设计缺陷与 CI 供应链隐患

以 CVE-2025-30066 事件为例,量化 GitHub Actions 在版本锁定、签名验证与运行时隔离上的缺失,并给出可落地的工程化防护参数。

2025 年 3 月,tj-actions/changed-files 这条被 2.3 万个仓库引用的 “明星” Action 在 6 小时内被植入恶意 Python 脚本,最终拿到 CVE-2025-30066,CVSS 8.6。事件本身并不复杂:攻击者先窃取维护者的个人访问令牌(PAT),再把 v44 标签指向包含 curl|bash 的 commit;下游工作流一旦拉取最新标签,机密就被写入公开日志。真正值得咀嚼的是 ——GitHub Actions 其实没有包管理器,却承担了现代软件供应链里最关键的包管理职能。本文把这次事件当成切片,拆三个设计缺陷,给一份可落地的参数清单,帮你在 “没有包管理器的包管理器” 上自建三重防护。

一、缺陷 1:标签可变,等同于 "latest" 地狱

npm、PyPI 在 registry 层面强制不可变版本号;而 GitHub Actions 的 “版本” 只是 git tag,任何人只要拥有推送权限,就能把 v3.1.2 瞬间移到另一 commit。OX Security 对 56 万个公开工作流扫描发现:

  • 68% 使用可变标签(@main、@v3)
  • 仅 9% 固定到 SHA

当标签可以被移动,缓存反而成了攻击放大器。GitHub 默认把 Action tarball 缓存 24 h,意味着恶意 commit 只要存在 1 min,就能在 24 h 内被无限复用,且不受回滚影响。

二、缺陷 2:令牌权限过宽,Secrets 成了 “单点爆破” 目标

工作流一旦使用 pull_request_targetworkflow_run,默认拿到 GITHUB_TOKEN 的写权限,还能访问仓库 Secrets。tj-actions 事件里,攻击者并不需要攻破目标仓库,只要让目标仓库引用被污染的 Action 即可。整个 CI 拓扑变成 “信任一根稻草,连带信任整捆稻草”—— 这正是供应链连锁反应的典型形状:

reviewdog/action-setup 被陷 → tj-actions/changed-files 被陷 → 下游构建的容器 / Helm 包被污染 → 私有集群被横向移动。

三、缺陷 3:零签名、零沙盒,运行即裸机

npm 从 2022 年开始要求发布签名,PyPI 支持 Sigstore;而 GitHub Actions 至今不验证作者签名,也不提供运行时隔离。Action 代码在宿主机上以 root 身份全权限执行,还能自由起 Docker、改内核参数。换句话说,只要引用一次恶意 Action,就等于把 runner 变成肉鸡

四、把风险算成数字:82 k 次 / 日的攻击面

用公开数据做一道简单算术:

  • 2.3 万仓库引用 tj-actions/changed-files
  • 平均每仓库 3 条工作流
  • 每条工作流每日触发 1.2 次

→ 单日潜在执行次数 ≈ 2.3 × 3 × 1.2 = 8.2 万次

其中只要有 1 次把 AWS Access Key 打印到日志,密钥就永久泄露;日志公开仓库可被任意搜索引擎索引,半衰期≈∞

五、可落地参数清单:把 “没有包管理器” 变成 “自建包管理器”

维度 推荐值 实施成本 备注
版本锁定 所有第三方 Action 固定到 full-length SHA GitHub UI 支持一键复制 SHA
标签保护 给核心仓库启用 “tag protection rule”,只允许 Maintainer 推 tag 极低 2024 年 10 月已 GA
Token 权限 在工作流顶部显式写 permissions: {},再按需增量放开 默认权限未来会收窄,先下手为强
缓存 TTL 把 Action 缓存设为 1 h,缩短攻击窗口 需自托管 cache service 或改 runner 配置
运行时隔离 对不可信 PR 使用 无网络 + 只读文件系统 的容器 runner 可用 gvisor + k8s 动态池
签名验证 要求内部 Action 上传 Sigstore provenance,CI 端用 cosign verify 2025 年 8 月 GitHub 已 beta 支持
供应链扫描 在 PR 阶段跑 StepSecurity/secure-workflows,自动检测未固定 SHA 或危险 trigger 开源,5 min 接完

把上表做成 .github/policy.yml 模板,随脚手架一起下发,就能把 “人为记得住” 变成 “系统拦得住”

六、结语:看见媒介,才能管控媒介

tj-actions 事件不是第一起,也不会是最后一起。GitHub Actions 的开放与灵活,让它成为现代 CI 的 “公共电网”;缺包管理器、缺签名、缺沙盒的三重缺失,又让它像一条没有保险丝的裸线。企业如果继续把 Actions 当成 “可信基础组件”,就必须自建版本锁定、最小权限、运行时隔离三重保险;否则,下一次被移动的 tag,可能就是你家生产集群的 “自毁按钮”。


参考资料
[1] 华盟网.《GitHub 藏在明处的 10 大媒介》. 2025-09.
[2] InfoQ.《热门 GitHub Action 遭供应链攻击》. 2025-05.

查看归档