研究报告 · 约 36,587 字 · 预计推送 4 部分

GitHub Actions 安全:权限、OIDC、依赖钉扎、Fork PR、Secrets 与供应链防护 —— 纵横综合报告 未开始

目录

题记与说明

版本:终稿(已按独立审读意见逐条修订,共 8 条,处理记录见文末"附录:审读意见处理记录")| 2026-11-01
综合方法:本报告由两份章节文件综合而成——纵轴篇《GitHub Actions 安全发展历程》(2018–2026 攻防演化时间线)与横轴篇《GitHub Actions 安全横向对比》(2026-11-01 时间截面上与 GitLab CI/CD、CircleCI、Jenkins、Azure DevOps、Bitbucket Pipelines、Buildkite 的六维对比)。两章均基于各自会话内的网络检索与官方文档抓取撰写,关键事实附来源链接;无法核验的数字在文中显式标注。
两章矛盾与重复的处理:① GhostAction 的"3 万+仓库 / 约 1900 账号"规模数字,纵轴原记为 Wiz 2025-09-30 的扩大评估、横轴原记为 2026 年 10 月的二手聚合报道,两处按字面互相矛盾(若 2025-09 已达 3 万+,一年后的"累计"不应仍是 3 万+)。本次修订经直接抓取 GitGuardian 2026-10-07 报告(10-13 更新)核实:3 万+ 仓库 / 约 1900 账号是 2026-10-08~09 新一波爆发的数字(约 1900 个被控账号向 30,000+ 仓库推送恶意 workflow),既非 2025-09 的存量评估、也非跨年"累计"口径;原稿所引 Wiz 原文链接本次抓取 404,"Wiz 2025-09-30 扩大评估"无法核验,已从正文移除。全稿统一为三波口径:2025-09 首波(GitGuardian 首轮确证)→ 2026-08~09 第二波 → 2026-10 第三波,详见纵轴·阶段四/阶段五与文末不确定点①。② tj-actions 的 payload 机制,纵轴写"把 secrets 以明文打进构建日志",横轴写"向日志倾倒 runner 内存"——本稿统一为"机制是倾倒 runner 内存,后果是 secrets 以明文进入构建日志"。③ tj-actions 与 GhostAction 的完整叙事两章均有展开,本稿将详细叙事收敛到纵轴·阶段四一处,横轴仅在对比语境下引用并标注"详见纵轴·阶段四",消除重复。

TL;DR

GitHub Actions 八年安全史是一条"便利优先 → 被攻击教会 → 默认收紧"的曲线:2018 年为增长留下三大隐患——默认读写的 GITHUB_TOKEN、把 secrets 带进 fork 上下文的 pull_request_target 逃生门、可被回溯改写的标签引用——外加一项生态风险:公共仓库可绑定 self-hosted runner;2021 年 Codecov 事件、2025 年 tj-actions 与 GhostAction 事件将其逐次击穿。平台以 2023 年 token 默认只读、2026 年执行策略 GA、工作流锁文件 GA、pull_request_target 默认禁用(2026-12-02 强制)完成从"用户开关"到"平台默认"的翻转。横向看,2026 年的 GitHub Actions 在权限粒度、OIDC 联邦、供应链出处(SLSA L3 原生 provenance)上居行业第一梯队,Secrets 完备度被 GitLab 的原生 Secrets Manager 反超,Fork 隔离默认态逊于 Bitbucket/Buildkite;它是攻击最集中的平台,也建了最厚的防护墙——因为生态规模最大。给用户的三句话:权限按 job 最小化并设 org 级默认只读;第三方 Action 优先用工作流锁文件(supersedes SHA pinning),否则钉扎完整 commit SHA;部署走 OIDC 联邦,消灭长期 secrets。各条建议的盘点命令、启用方式、以及 2026-12-02 强制的后果与豁免路径,见 3.3 落地路径。


一、纵轴:发展脉络(2018-10 – 2026-11)

一句话总纲:GitHub Actions 的安全史,本质是一条"便利优先 → 被攻击教会 → 默认收紧"的曲线——2018 年以"自动化工作流"的面目诞生时几乎不考虑 fork 场景的威胁模型;2020–2021 年社区研究和 Codecov 事件迫使平台补上权限、审批、OIDC 等开关;2025 年 tj-actions 供应链攻击与 GhostAction 事件(2025-09 首波,延续至 2026)把"信任第三方 Action"的假设彻底击穿;到 2026 年,GitHub 终于把安全从"用户自己开"翻转为"平台默认关"。

阶段总览

阶段时间主题标志性节点
1. 诞生与便利优先2018.10–2019抢占 CI/CD 市场有限公测(2018-10-16)、GA(2019-11-13)、自托管 runner(2019-11)、pull_request_target 引入(2019 末–2020)
2. 第一波安全审视2020–2021漏洞研究 + 事件驱动补课Pwn Request 研究、Codecov 事件(2021-04)、首次贡献者审批(2021-04)、permissions 键(2021-08)、OIDC(2021-10)
3. 默认安全化与研究深化2022–2024权限模型翻转、攻击面学术化GITHUB_TOKEN 默认只读(2022-10 宣布 / 2023-02 生效)、缓存投毒系统化公开(2024-05 深度研究)、PyTorch 攻击验证(2024-01)、ArtiPACKED(2024-08)、Cacheract 缓存蠕虫 PoC(2024-12)
4. 信任链危机2025第三方 Action 失信之年(延续至 2026)tj-actions 挪标签攻击(2025-03)、CISA 警报、官方推 SHA 钉扎、GhostAction 首波(2025-09)
5. 平台级"默认安全"重构2026 至今从开关到平台策略GhostAction 第二波(2026-08–09)与第三波(2026-10)、执行策略 GA(2026-09-17)、锁文件预览→GA(2026-10-14/28)、公共仓库默认禁用 pull_request_target(2026-12-02 强制)

1.1 阶段一:诞生与便利优先(2018–2019)

驱动因素:微软收购 GitHub(2018-06)后需要快速补齐 CI/CD 短板,产品逻辑是增长优先——最宽松的默认值(GITHUB_TOKEN 读写、fork PR 事件灵活触发、公共仓库开放 self-hosted runner 绑定)都是为了让"五分钟上手"成立。安全在这个阶段是文档里的脚注。后来反复出事的三大隐患全部埋于此时——默认读写的 token、会把目标仓库 secrets 交给 fork 触发上下文的 pull_request_target、可被回溯改写的标签引用;外加一项同期埋下的生态风险:公共仓库可被外部 PR 绑定的 self-hosted runner(平台默认值问题)。

1.2 阶段二:第一波安全审视(2020–2021)

驱动因素:Codecov 事件是分水岭——它证明了"CI 是新的内网",直接催生 GitHub 官方《Security hardening for GitHub Actions》加固文档体系(见 docs: OpenID Connect 概念页 等)和 OIDC 落地。社区侧,OpenSSF Scorecard(2020 年推出)与 SLSA 框架(2021 年成型,此为模型既有知识,供上下文参考)也在推动"CI 供应链"成为独立议题。

1.3 阶段三:默认安全化与研究深化(2022–2024)

驱动因素:默认值终于翻转,靠的是"存量用户不会自己改设置"的平台责任逻辑(官方在 changelog 中明说旧默认太宽松);研究侧则进入学术化——pwn request、缓存投毒、artifact 竞态、缓存蠕虫,攻击面被系统测绘完毕,只差一次大爆发的引信。

1.4 阶段四:信任链危机(2025)

驱动因素:tj-actions 的"标签可被回溯改写"击穿了 @v4 这类浮动引用的全部信任假设——今天审计过的代码不等于明天执行的代码。研究方给出的"全 SHA 钉扎"是正确但昂贵的手工答案:据 Wiz 研究的二手转引(原始 Wiz 页面本次未能定位,见文末不确定点②),全量 SHA 钉扎的仓库只占约 3.9%——用户侧修复采用率过低,直接铺垫了 2026 年的平台化方案。(GhostAction 随后于 2026-08–09 与 2026-10 两度复现并显著扩大,叙事见阶段五。)

1.5 阶段五:平台级"默认安全"重构(2026 至今,截至 2026-11-01)

驱动因素:八年教训收敛为一个判断——把安全决策留给两亿仓库的维护者是不现实的;pull_request_target 的 Pwn Request 类漏洞、标签挪用类供应链攻击都被证明"用户侧修复采用率过低"(GhostAction 三波复现是最新证据),必须由平台以默认规则 + 锁文件 + 执行策略三层兜底。

1.6 纵轴小结:驱动因素与参与者全景

  1. 便利与安全的原生张力:Actions 的每一步安全演进,几乎都是对诞生期默认值的追溯修正——默认读写的 token(2023 才翻转)、把 secrets 带进 fork 上下文的 pull_request_target(2026 才默认禁用)、可变标签引用(2026 才有锁文件);外加同期埋下的生态风险:公共仓库可绑定 self-hosted runner(官方至今的措辞仍是"几乎绝不")。新功能先跑,安全后付账。
  2. 事件驱动强于前瞻设计:Codecov(2021)→ 加固文档与 OIDC;ArtiPACKED(2024)→ artifact v4 与清理实践;tj-actions(2025)→ SHA 钉扎与锁文件。平台的每次大幅收紧,背后都站着一次公开的重大事故。
  3. 研究社区是隐性主角:GitHub Security Lab 的 Pwn Request 分类、Unit 42、SonarSource、Adnan Khan、StepSecurity 构成了从"发现一个漏洞"到"定义一类漏洞"的产业研究链路,官方默认策略大量建立在这些分类之上。
  4. 责任归属的三级跳:用户自己加固(2020–2022 文档化)→ 平台给更好用的开关(2021–2025 permissions 键、审批、OIDC、SHA 钉扎设置)→ 平台直接下发默认策略(2026 执行策略、锁文件、默认禁用)。
  5. Secrets 主题的演化路径:明文环境变量(2019)→ 环境级 secrets 与保护规则(2021)→ OIDC 短时凭据替代长期 secrets(2021-10)→ "日志即泄露面"(tj-actions 把 secrets 打进构建日志)→ 运行时出口监控(Harden-Runner)与平台级异常运行拦截(2026)。

二、横轴:横向对比(2026-11-01 时间截面)

把 GitHub Actions 放在 2026 年 11 月 1 日的 CI/CD 安全赛道上,与 GitLab CI/CD、CircleCI、Jenkins、Azure DevOps Pipelines、Bitbucket Pipelines、Buildkite 六家对比。竞品入选逻辑:同处 2026 年、面向同类工作负载、必须回答同一组安全问题(权限下发、身份联邦、Secrets 存放、不可信代码执行、制品完整性)的平台。

2.1 总览对比表(2026-11-01 截面)

维度GitHub ActionsGitLab CI/CDCircleCIJenkinsAzure DevOpsBitbucket PipelinesBuildkite
权限模型★★★★★ permissions: 键可到 job 级,GITHUB_TOKEN 可强制默认只读★★★☆ CI_JOB_TOKEN 作用域可配,细粒度靠 protected 分支/环境★★★☆ contexts + restricted contexts★★☆ 全靠 RBAC 插件★★★★ 构建服务账号 + 默认限权选项★★☆ 仓库/工作区两级,粗粒度★★★★ Teams RBAC + agent 权限在自己手里
OIDC 短期凭证★★★★★ 原生,id-token: write,联邦 AWS/GCP/Azure★★★★★ id_tokens 关键字 per-job JWT,原生 Vault/AWS★★★★★ V1/V2/V3 token,claims 粒度业界最细之一★★☆ 无原生,靠 OIDC 插件★★★☆ 服务连接支持 Workload Identity Federation★★★★ 官方 OIDC IdP,联邦 AWS/GCP/Vault★★★★ 官方首选策略即 OIDC 联邦
Secrets 管理★★★★ org/repo/environment 三级 + masking;无原生外部 vault★★★★★ 变量 protected/masked/hidden + 原生 Secrets Manager(OpenBao)★★★★ contexts 可跨项目共享与限制★★★ Credentials Store + Binding 插件(历史 CVE)★★★★ variable groups + Azure Key Vault 直连★★★ secured 变量,无 vault★★★★ 平台不存 secrets,hooks 在你自己的基础设施
Fork PR 隔离(按"默认安全性"评定,见表注)★★★☆ 默认不下发 secrets(GITHUB_TOKEN 只读)+ 首次贡献者需审批,但 pull_request_target 是默认可用的高危逃生门★★★★☆ fork MR 流水线在 fork 上下文运行,上游 protected 变量不可达★★★★ 默认不向 fork 构建传 secrets,开启需 OIDC claim 校验★★ 无内置 fork 概念,全靠自建★★★★ fork 构建默认禁 secrets,可关(有 Defender 策略盯防)★★★★★ fork PR 根本不触发流水线,无开关★★★★★ secrets 不出你的基础设施,fork 默认拿不到
供应链防护(签名/出处)★★★★★ attest-build-provenance + Sigstore,官方宣称可达 SLSA L3★★★☆ Ultimate 内置扫描套件,provenance 需自建 cosign★★★ security orbs + config policies★★ 插件供应链是最大风险源★★★ 与 Defender for Cloud 联动★★ 提供 git-secrets-scan 工具★★★ 无平台级签名,可自建 Sigstore
第三方加固工具生态★★★★★ zizmor、Harden-Runner、Scorecard、pinact…★★★ 内置扫描为主★★ orbs 生态★★ 插件市场(良莠不齐)★★ 扩展市场★★★★
近年重大安全事件tj-actions(2025-03)、GhostAction(2025-09 首波、2026-08–09 第二波、2026-10 第三波;详见纵轴·阶段四/阶段五)平台级事故较少2023-01 全客户 secrets 泄露事件常年插件 CVE 流无标志性集中事件无标志性集中事件无标志性集中事件
成本模型(Linux 主力档)$0.006/min(2026-01 起降价约 39–40%,新增 $0.002/min 平台费)按席位订阅(Premium $29/人/月,Ultimate 报价制,数字未核验)credits 计费,Performance $15/月起(二手)软件免费,人力+基础设施成本最高订阅 + 并行作业付费按席位 + 构建分钟按席位,计算自理
表内星级为本研究的定性评估,依据下文逐项来源,非任何第三方评分。各行衡量该维度的综合实现水平;唯一例外是 Fork PR 隔离行:按 2.5 的"默认安全性"口径评定(Bitbucket ≈ Buildkite > GitLab ≈ Azure > GitHub 默认态),"可用性 × 安全"的综合体验讨论见 2.5 与 2.9。

2.2 权限模型:GitHub 的 permissions: 键仍是行业最细粒度

GitHub Actions 的核心武器是 permissions: 键:可在 workflow 级和 job 级给 GITHUB_TOKEN 逐权限收窄,官方安全参考明确建议"将 GITHUB_TOKEN 的默认权限设为只读,再按 job 提权",并提供阻止"workflows 创建或批准 PR"的开关与环境 secrets 的 required reviewers 机制(GitHub Docs: Secure use reference,本次会话直接抓取核对)。对比之下:GitLab 没有等价的 per-job token 权限键,权限模型围绕"protected 分支/标签 + protected 变量 + protected 环境"展开;CircleCI 用 contexts 与 restricted contexts 把 secrets 访问限制到指定分支/安全组,但没有"每个 job 一份低权 token"的概念;Jenkins 最弱,核心只提供 matrix-based 授权,pipeline 级最小权限要装 Role-based Authorization 等插件自行拼装(第三方加固清单 2026);Azure DevOps 默认可勾选"Limit job authorization scope to current project"等开关把构建服务账号的可达范围压小(Microsoft Learn);Buildkite 本质上把权限问题外包给自托管 agent 的宿主,平台只做编排。

结论:以"声明式、可下沉到 job 的最小权限"为标准,GitHub Actions 仍是第一梯队;GitLab/Azure 靠环境与分支保护"曲线救国"居第二梯队;Jenkins 属需要大量插件与人工纪律的第三梯队。

2.3 OIDC 短期凭证:2026 年已是全行业标配,比拼点转向 claims 粒度

七家平台里六家已原生支持 OIDC 联邦,唯一例外是 Jenkins(靠社区插件,社区讨论)。这是 2023→2026 三年间最大的行业收敛。GitHub:声明 permissions: id-token: write 即可拿 OIDC token,与 AWS/GCP/Azure 联邦(Secure use reference)。GitLab:id_tokens 关键字按 job 生成 JWT,且 job 必须先声明至少一个 ID token 才能用 secrets: 从 Vault 拉取,把"拿凭证"与"取秘密"绑定在同一份身份声明上(GitLab Docs: Secrets)。CircleCI:token 注入为 $CIRCLE_OIDC_TOKEN(V1/V2/V3 三版并存,V3 仅 Cloud,有效期一小时),V3 的 sub claim 包含 checkout-source 与 config-source,云侧信任策略可校验"流水线配置本身来自哪个仓库哪个分支"(CircleCI Docs: OIDC tokens,本次会话直接抓取核对)。Bitbucket 官方提供 OIDC IdP 与 AWS/GCP/Vault 的联邦指引(Atlassian 文档);Buildkite 官方安全清单把 OIDC 联邦、让长期凭证根本不存在列为 secrets 策略第一优先(Security checklist);Azure DevOps 服务连接支持 Workload Identity Federation,但对非 Azure 云的联邦体验不如前述顺滑。

结论:GitHub/GitLab/CircleCI 三家并列第一梯队;差异已从"有没有"转移到"信任策略能在多细的维度上校验调用方"——CircleCI V3 的 config-source claim 与 GitHub 的 environment 绑定是两个代表。

2.4 Secrets 管理:GitLab 凭原生 Secrets Manager 反超,Buildkite 架构哲学不同

GitLab 在 2025–2026 年补齐了最短的一块板:基于 OpenBao 的原生 Secrets Manager,secrets 可按 job、分支、环境作用域收窄并已宣布 GA(GitLab Docs;GitLab 官方博客),加上变量的 protected/masked/hidden 三标志,成为七家中唯一"内置变量体系 + 内置 secrets 管理 + 外部 Vault 联动"三层齐备的平台(判定口径:这里指全部由平台官方原生提供;GitHub 的 marketplace vault action 是第三方集成,不计入本口径——若放宽为"存在任何 vault 集成途径",GitHub 亦可算作三层,但并非官方原生)。GitHub 提供 org/repo/environment 三级 secrets 与日志 masking,配套 secret scanning + push protection——公共仓库免费自动启用,组织私有/内部仓库则需 GitHub Secret Protection(原 Advanced Security 体系拆分后的付费加购)(官方文档,本次会话直接抓取核对);原生外部 vault 集成缺席,靠 marketplace 的 vault action 补位。CircleCI 的 contexts 支持跨项目共享与限制,但 2023-01 泄露事件暴露了"平台集中托管 secrets"的单点风险:攻击者通过员工笔记本上的 infostealer 偷到带 2FA 的 SSO 会话 cookie 进入内部系统后,要求全体客户立即轮换存储在 CircleCI 中的所有 secrets(官方事件报告)——这场事件是行业转向"OIDC 优先、少存 secrets"的直接推手之一。Jenkins 的 Credentials Store + Credentials Binding 插件负责存储与日志 masking,但插件体系本身有 CVE 历史(如 2023-04-12 官方安全通告涉及凭据绑定与权限检查缺失)。Azure DevOps 的 variable groups 可直连 Azure Key Vault。Buildkite 根本不提供平台托管 secrets 的默认路径:secrets 放在你自己基础设施的 hooks/vault 里,平台只见编排不见秘密——对"平台侧单点泄露"天然免疫,代价是运维责任 100% 在用户。

2.5 Fork PR 隔离:本课题的核心差异点,七家走出三种哲学

这是七个平台分歧最大、也最能体现设计哲学的维度:

  1. GitHub:"默认可用但收权 + 一个高危逃生门"。官方原文明确:"With the exception of GITHUB_TOKEN, secrets are not passed to the runner when a workflow is triggered from a forked repository"(Events that trigger workflows;Using secrets in GitHub Actions),fork 触发的 pull_request 中 GITHUB_TOKEN 只读,首次外部贡献者的 workflow 默认需维护者批准(2021-04 起,见纵轴·阶段二)。但 pull_request_target 触发器在基础仓库的安全上下文运行、自带 secrets 与写权限,官方文档警告"Avoid using the pull_request_target workflow trigger if it's not necessary",并提供专文《Securely using pull_request_target》与 workflow_run 替代方案;官方对公共仓库使用自托管 runner 的措辞极其强硬:"should almost never be used for public repositories"。社区安全讨论将其列为头号误用源,强调"fork 的 PR 数据必须当作潜在恶意输入"(GitHub 社区 Harden 讨论帖,2025-07)。
  2. GitLab:"在 fork 上下文运行"。fork 的 MR 流水线使用 fork 项目自己的 CI/CD 配置、runner 与变量,上游项目的 protected 变量对其不可达;"让 fork 流水线跑到父项目"的 epic(#3278)多年搁浅,卡点正是安全模型(GitLab Docs: Merge request pipelines)。
  3. Bitbucket:"默认禁用,无开关"。官方文档明确"Pull requests from a forked repository don't trigger the pipeline",且没有任何官方开关能让 fork PR 流水线跑起来;社区 workaround 都是"先合并进主仓分支再跑 CI"(Reddit r/devops 讨论)。最安全,功能牺牲也最大。
  4. CircleCI:"默认不传,开了要自己验证身份":fork 构建默认不生成 OIDC token、不传 secrets;若开启"Pass secrets to builds from forked pull requests",官方要求在云侧信任策略中校验 checkout-source/config-source claims(CircleCI Docs)。
  5. Azure DevOps:"默认禁 secrets,可关,有雷达":fork 构建默认无法访问 secrets,管理员可开启;Defender for Cloud 有专门策略项《Azure Pipelines should not have secrets available to fork builds》盯着这个开关(Microsoft Learn)。
  6. Jenkins:无 fork 概念,隔离完全靠自建(独立 agent 池、按 job 划分 credentials 域),等于把 GitHub 用平台能力解决的安全题留白给用户。
  7. Buildkite:平台不持有 secrets,fork PR 默认接触不到任何平台侧秘密(Buildkite Docs)。

结论:默认安全性 Bitbucket ≈ Buildkite > GitLab ≈ Azure > GitHub(默认态)——2.1 表 Fork PR 隔离行的星级即按此口径评定;但可用性 × 安全的综合体验 GitHub 与 GitLab 更好——GitHub 用"收权 + 审批 + 逃生门需自证"换灵活性,代价是 pull_request_target 成为行业级事故温床(如 2024 年 asyncapi-bot 事件,见 Wiz: Hardening GitHub Actions)。

2.6 依赖钉扎与供应链防护:GitHub 被"自己的规模"反噬,也建了最厚的墙

GitHub Actions 的第三方 Action 生态是七家中唯一把"复用别人写的 CI 组件"变成主流默认的平台,这既是它最大的效率优势,也是最大的攻击面。标志性事件(tj-actions、GhostAction 的完整叙事见纵轴·阶段四与阶段五)共同证明了:平台安全文档写得再好,生态里"用 tag 引用第三方 action"的存量习惯才是真实防线。

平台侧回应与对手对比:

结论:按"供应链防护纵深"排序是 GitHub > GitLab > 其余。GitHub 的独特处境是:攻击最猖獗的平台,同时是防护基建最完善的平台——攻击规模恰恰因为它的生态规模(同类上的"Windows 桌面困境")。

2.7 第三方加固工具生态:只有 GitHub 长出了"围绕 CI 平台本身的安全工具品类"

2026 年截面,围绕 GitHub Actions 已形成独立工具品类,其他平台基本没有对应物:zizmor(William Woodruff 主导的 workflow 静态分析器,扫描凭据泄露、pwn-request、模板注入等模式,2024-10 发布,已成社区事实标准,zizmor.sh;zizmorcore/zizmor;Open Source Security 访谈, 2025-05);StepSecurity Harden-Runner(agent 级出口监控,tj-actions 事件中的关键检测手段,Wiz 分析);配套还有 OpenSSF Scorecard、pinact(自动 SHA 钉扎)、Dependabot 对 workflow 依赖的版本升级。其他平台:GitLab 把对应能力内建为产品,CircleCI 靠 orbs,Jenkins 靠插件市场——但"社区安全研究者针对 CI 配置本身做静态审计工具"这一现象只在 GitHub Actions 生态出现,原因直白:生态规模大到养得起。

2.8 成本:安全含义藏在计费模型里

从安全视角看计费:"平台托管 secrets 越多、平台被攻破的爆炸半径越大"——CircleCI 2023 事件让全行业为其买单一周的 secrets 轮换;而 OIDC/自托管模式在成本表上"便宜"的只是表,安全责任计入了另一张表。

2.9 适用场景结论

团队画像推荐理由
开源项目、重度 fork 协作GitHub Actions / GitLab默认隔离 + 审批 + 生态工具(zizmor 等)最全;Bitbucket 最安全但 fork PR 无法触发 CI,功能代价大
合规重型、要审计与扫描套件GitLab Ultimate,或 GitHub Enterprise + Secret Protection + attestations前者扫描内建,后者供应链出处(SLSA L3)内建
极致控制、安全责任自担Buildkitesecrets 不出你的基础设施,平台被攻破不等于 secrets 被攻破
深度 Azure 生态Azure DevOpsKey Vault 联动 + Defender 策略盯防 fork 开关
已有 Jenkins 资产继续用,但按"插件最小化 + OIDC 插件 + 独立 agent 域"加固无原生能力,一切靠纪律

三、交叉洞察:两轴结合说明了什么

单看纵轴,这是一个"平台被事故推着走"的故事;单看横轴,这是一张"2026 年各家功能对照表"。两条轴交叉之后,才能看到 GitHub Actions 安全问题的真实结构,以及普通用户应该怎么判断和行动。

3.1 五条洞察

洞察一:GitHub 的安全短板从来不是"能力短板",而是"默认值与存量习惯的短板"——2026 年的翻转正在补上这一课。

横轴显示,GitHub 在权限粒度(唯一可下沉到 job 的 permissions: 键)、OIDC、供应链出处(唯一原生 SLSA L3 provenance)上都是第一梯队;纵轴则显示,这些能力发布到"默认生效"平均晚了三到五年——permissions 键 2021-08 就有 beta,默认只读 2023-02 才对新仓库生效;OIDC 2021-10 就有,但"全 SHA 钉扎的仓库只占约 3.9%"(Wiz 研究的二手转引,见文末不确定点②)说明存量习惯根本不跟随。能力与默认值的错位,正是 tj-actions、GhostAction 能持续得手的结构性原因。2026 年的执行策略、锁文件、pull_request_target 默认禁用(12-02 强制),本质上是平台承认"提供开关不等于解决问题",把安全决策从两亿仓库的维护者手里收回来。横轴的另一个佐证是:GitLab/Azure 的权限模型粒度不如 GitHub,但靠 protected 资源这类"硬默认边界",平台级标志性事故反而更少——谁能在 org/instance 层强制安全默认值,谁的存量事故少(当然,事故更少部分也因其生态规模更小,见洞察二)。

洞察二:攻击集中度与防护繁荣度是同一枚硬币的两面,都不是"最弱"的证据。

横轴的重大事件一栏里,GitHub Actions 独占两行(tj-actions、GhostAction 三波),Jenkins 是常年插件 CVE 流,其余四家几乎空白。表面看 GitHub 最不安全;但纵轴的阶段划分显示,这些攻击全部命中的是诞生期遗留的默认值与生态习惯(逃生门事件、tag 浮动引用),而非平台当前防护的失守——Coder 靠 SHA 钉扎自动躲过 tj-actions 就是反证。同时,只有 GitHub 生态养出了 zizmor、Harden-Runner、pinact 这样的第三方安全工具品类。这是"Windows 桌面困境"的 CI 版:攻击者追着规模最大的目标打,平台被攻击教会得也最快。对用户的推论是:不能因为事故新闻多就判定 GitHub Actions 不安全,也不能因为防护文档全就默认自己安全——事故集中在"没跟上默认值"的存量仓库里,你要确认自己不在其中。

洞察三:Codecov(纵轴转折点)与 CircleCI 2023(横轴转折点)共同把行业推向同一个终局:消灭长期 secrets,而不是保护它们。

纵轴的 Secrets 演化路径止于"OIDC 短时凭据替代长期 secrets";横轴则给出了 Secrets 存放位置的三极收敛:平台托管(便利但单点,CircleCI 2023 为证——一次员工笔记本沦陷逼全行业轮换 secrets)→ 自托管(Buildkite 模式,平台不存秘密但责任 100% 外包)→ 无长期凭证(OIDC 联邦,行业终局)。2021 年 Codecov 事件证明了"CI 环境变量里的秘密就是攻击者的提款机",2023 年 CircleCI 事件证明了"连平台集中托管也扛不住自身被攻破"。两次事件分别从"怎么存"和"存在哪"两个方向论证了同一个结论:唯一的正解是让秘密在 CI 里不存在。GitLab 2025–2026 补的原生 Secrets Manager 是对"必须托管"场景的补全,而所有平台的安全清单(Buildkite 尤其直白)都已把"OIDC 联邦、让长期凭证根本不存在"列为第一优先。

洞察四:pull_request_target 是纵轴与横轴的最佳交汇样本——横轴的"设计哲学差异"其实是在描述纵轴"事故史"的分布。

横轴发现七家 fork PR 隔离有三种哲学:GitHub"默认可用但收权+逃生门"、GitLab"在 fork 上下文运行"、Bitbucket"默认禁用";纵轴则完整记录了 GitHub 逃生门从便利(2019–2020 引入)到被研究定型(2020 Pwn Request 分类)到事故温床(PyTorch 攻击验证、缓存蠕虫 Cacheract、GhostAction 复用该向量)到被平台关停(2026-09 宣布默认禁用、12-02 强制)的全生命周期。两轴合起来看:GitHub 的逃生门贡献了该领域最多的接管事故,但也倒逼出最详尽的官方反模式文档与替代方案;GitLab 的 fork 上下文模型让同类问题根本不存在,代价是 fork 流水线能力多年搁浅;Bitbucket 用功能缺失换安全,在 2026 年显得过度保守。这提示一个通用判断框架:评估任何平台的 fork/不可信代码模型,不要只看默认态星数,要看"逃生门的宽度和逃生门上装的锁"。

洞察五:责任归属的三级跳是行业规律,不是 GitHub 特例;且它正在所有平台上重演。

纵轴总结出"用户自己加固 → 平台给开关 → 平台下发默认策略"的三级跳。放到横轴上检验:GitLab 把安全扫描内建为 Ultimate 套件(第二级到第三级之间)、Azure DevOps 用 Defender 策略直接盯防用户的安全开关(第三级)、CircleCI 在 2023 事件后强制全客户轮换 secrets 并转向 OIDC 优先(事件驱动式的第三级)、Jenkins 停留在第一级(一切靠纪律)。这说明三级跳不是 GitHub 的独有叙事,而是整个 CI/CD 行业在 2020–2026 年的普遍运动方向——平台正在吃掉用户的安全责任。对用户而言这意味着:选平台时应把"平台愿意替你强制什么默认值"作为比"平台能配置什么"更重要的指标。

3.2 对用户的判断与建议

综合两轴证据,按优先级给出可执行清单(针对使用 GitHub Actions 的团队;选型建议见横轴·适用场景表;每条的落地操作见 3.3):

  1. 【最高优先级·2026-12-02 前】盘点并迁移所有 pull_request_target 工作流。平台默认禁用的强制日期临近(纵轴·阶段五);能改 pull_request + workflow_run 的改,确需保留的走执行策略白名单显式声明,并对照官方反模式文档自查"显式 checkout 不可信 PR 头"这类 Pwn Request 模式(Securely using pull_request_target、Pwn Request 分类)。盘点命令、强制后的具体后果与豁免方式见 3.3(1)(2)。
  2. 【供应链】第三方 Action 从 tag 钉扎升级到工作流锁文件。锁文件已 GA(2026-10-28),官方定位是"supersedes SHA pinning"——保留 @v4 可读性同时锁死实际执行的 commit(启用方式与能力边界见 3.3(3));存量仓库暂时做不到锁文件的(原因见 3.3(3)),至少钉扎完整 commit SHA 并验证 SHA 来自原仓库而非 fork(锁文件文档、Secure use reference)。CISA 已就 tj-actions 事件发布官方警报,其缓解建议以"审计影响窗口、立即轮换 secrets、更新到修复版本"为主,并将 GitHub 官方加固文档列为参考(见纵轴·阶段四);对"锁文件优先"的平台层方案,尚无政府级背书,本报告不据此引申。
  3. 【权限】org/enterprise 级把 GITHUB_TOKEN 默认权限设为只读,再按 job 用 permissions: 键提权。这是官方安全参考的明确建议;2023 年的默认翻转只覆盖新建仓库,存量仓库要手动改。同时开启"禁止 workflows 创建或批准 PR"。
  4. 【Secrets】用 OIDC 联邦替代长期云凭证,尽量减少平台托管 secrets 的数量。permissions: id-token: write + 云侧信任策略是零长期凭证的标准路径;部署类 secrets 用 environment + required reviewers 绑审批链。参考 CircleCI 2023 教训:你托管的每一个 secret 都是平台的爆炸半径。
  5. 【自托管 runner】不要把 self-hosted runner 绑定到公共仓库。官方措辞是"should almost never be used for public repositories"——fork PR 代码可在其上持久化沦陷。
  6. 【工具链】把 zizmor 纳入 CI 静态检查、用 OpenSSF Scorecard 自评、敏感流水线加 Harden-Runner 类出口监控。这三个工具本身就是 tj-actions 类攻击的检测面(Harden-Runner 正是 2025-03 的首发检出来源)。安装命令与接入写法见 3.3(4)。
  7. 【制品】发布渠道启用 Immutable Releases + artifact attestations。前者堵"挪标签"攻击,后者给你的制品生成可验证的 SLSA 出处。
  8. 【选型】若安全责任无法自担,参考横轴结论:重度 fork 协作选 GitHub/GitLab;合规重型选 GitLab Ultimate 或 GitHub Enterprise + Secret Protection;要"平台被攻破 ≠ secrets 被攻破"选 Buildkite;已有 Jenkins 资产则按"插件最小化 + OIDC 插件 + 独立 agent 域"加固,不要指望平台默认值兜底。

3.3 落地路径:每条建议怎么上手(2026-11-01 时点)

3.2 回答"做什么",本节回答"怎么做"——每条配盘点手段、启用方式与工具入口,并回答 2026-12-02 强制的后果与豁免。所引机制与命令均经本次会话直接抓取官方文档核验(标注见文内)。

(1)先盘点:知道自己暴露在哪

  total=$(grep -rhE 'uses:' .github/workflows | wc -l)
  pinned=$(grep -rhE 'uses:[^@[:space:]]+@[0-9a-fA-F]{40}' .github/workflows | wc -l)
  echo "$pinned / $total"

(粗口径:只看本仓库 workflow 文件,不含可复用工作流内部的引用。)

(2)2026-12-02 强制:后果与豁免

(3)工作流锁文件:启用方式、能力边界、为什么存量仓库"暂时做不到"

(4)三个工具的上手路径

  - name: Harden Runner
    uses: step-security/harden-runner@05e31511f85b41b11d1cf0ef85d0992719546e2c # v2.21.0
    with:
      egress-policy: audit

先用 audit(只记录)跑出基线,再切 block 按自动生成的域名允许列表阻断未授权外传;注意全局黑名单在 audit 模式下也强制生效(仓库 README,本次会话直接抓取核对;tj-actions 正是由它于 2025-03 首发检出)。

  - uses: ossf/scorecard-action@<full commit SHA> # v2.6.0 or later
    with:
      results_file: results.sarif
      results_format: sarif
      publish_results: true

注意 publish_results: true 要求 job 权限含 id-token: write;结果在仓库 Security 标签的 Code Scanning Alerts、scorecard.dev 徽章与 API 查看;无法用托管面板的私有仓库可按标准安装说明本地运行 scorecard CLI(ossf/scorecard-action README,本次会话直接抓取核对)。

(5)建议的落地次序(对应 3.2 优先级):盘点(pull_request_target 使用面 + SHA 覆盖率)→ 开 evaluate 影子模式看 12-02 影响清单 → 迁移或白名单 pull_request_target → 新仓库/重点仓库上锁文件,其余先钉 SHA → org 级默认只读 token → OIDC 联邦替代长期 secrets → zizmor 进 CI + 敏感流水线挂 Harden-Runner + Scorecard 季度自评。


四、参考来源

官方 Changelog / 博客(GitHub)

官方文档(各平台)

事件、研究与工具

第三方博客与社区讨论(非官方来源)

不确定点与免责声明(承袭两章标注,修订后汇总如下)

  1. GhostAction 规模数字(本次修订已统一口径):原稿纵轴记"Wiz 2025-09-30 扩大评估 3 万+ 仓库 / 约 1900 账号"、横轴记"2026-10 累计扩散",两口径按字面互相矛盾。本次修订直接抓取 GitGuardian 2026-10-07 报告(10-13 更新)核实:3 万+ 仓库 / 约 1900 账号为 2026-10-08~09 新一波爆发(约 1900 个被控账号、目标 30,000+ 仓库),772 仓库 / 2,577 secrets / 373 用户为 2026-08-31~09-30 第二波,817 仓库 / 327 用户 / 3,325 secrets 为 2025-09 首波;原稿所引 Wiz 原文(ghostaction-campaign-github-workflows)本次抓取 404,"Wiz 2025-09-30 扩大评估"无法核验,已从正文移除。
  2. 全量 SHA 钉扎占比约 3.9%:多条第三方安全博客转引称为 Wiz 研究结果(Arctiq、Stéphane Robert 等,链接见上节),但原始 Wiz 页面本次未能定位(Wiz 2026-10-26 的 pwn request 研究中亦无此数),原始统计口径与样本未核验——按本报告标注方法,正文两处均标为"二手转引"。
  3. GitLab 定价(Premium $29/人/月、Ultimate 报价制):官方定价页抓取超时,数字来自搜索结果聚合,未核验。
  4. GitHub $0.002/min 平台费对自托管 runner"已回撤":来自二手报道与社区讨论,未逐条核对官方 changelog 原文;hosted runner 现行费率已由官方计费文档直接核验。
  5. pull_request_target 引入时间:原始 changelog 存档未检索到,按 GitHub 官方讨论表述为"2019 末–2020 年前后"。
  6. 2026-06-18 Policies 预览与 2026-10-18 官方博客:仅经搜索摘要确认,未逐字抓取核验。
  7. OpenSSF Scorecard(2020)与 SLSA(2021)的时间点:模型既有知识,供上下文参考,非本次会话核验。
  8. 对比表星级:为本研究的定性评估,依据上文标注来源;其中 Fork PR 隔离行按"默认安全性"口径评定(与 2.5 结论一致),其余各行衡量综合实现水平,均非任何第三方基准测试。
  9. 本次修订中改写的引用:① 原稿"2023 年研究员 Adi Katz 公开缓存投毒"未能定位其原始发布(其署名的 Unit 42 ArtiPACKED 为另一研究,现仅用于 ArtiPACKED 本身),已改用可核验的 Adnan Khan 与 GitHub Security Lab 来源;② 原稿"GitHub Actions Worm 研究(2024)"归名 Adnan Khan 并引其 2023-12 开场帖、另引 Horizon3《PWN Request》——本次核验:adnanthekhan.com 的 GitHub Actions 标签下仅有 3 篇、无 worm 专文,Horizon3 链接抓取 404,已改用其已核验的缓存投毒与 Cacheract 研究(自传播/蠕虫化表述保留,原稿的 TOCTOU 审批绕过等未核验细节已删除);③ 原稿引用的 Wiz GhostAction 链接 404,首波叙事改以 GitGuardian 为准;④ reddit 链接原稿误标为"Atlassian 社区讨论",已改标 Reddit。

附录:审读意见处理记录(8 条)

#审读意见处理结果
1GhostAction 数字时间线自相矛盾(卷首①、阶段四 65–66 行、不确定点①)直接抓取 GitGuardian 2026-10-07 报告(10-13 更新)核实:3 万+ 仓库 / 约 1900 账号为 2026-10-08~09 第三波爆发,非 2025-09 存量、也非累计口径;"Wiz 2025-09-30 扩大评估"所引 Wiz 原文 404、无法核验,已移除。全稿统一为三波口径(2025-09 首波 / 2026-08~09 第二波 / 2026-10 第三波),卷首①、阶段四、阶段五、横轴事件行、不确定点①同步改写。
2星级表与 2.5 结论冲突、表注未说明口径Fork PR 隔离行改按 2.5 的"默认安全性"口径评定:GitHub ★★★★☆→★★★☆、Buildkite ★★★→★★★★★,其余不变;表注写明"该行按默认安全性评定,其余各行衡量综合实现水平",并在 2.5 结论句中回指表注。
3"三大隐患"三处清单不一致统一为"三大隐患(默认读写 token、pull_request_target 逃生门、可回溯改写的标签引用)+ 一项生态风险(公共仓库可绑定 self-hosted runner,平台默认值问题)";TL;DR、阶段一驱动因素、纵轴小结第 1 条三处同步。
4引用错位与标签不符reddit 链接改标"Reddit r/devops 讨论"(正文与来源列表两处);Unit 42 链接不再同时支撑缓存投毒与 ArtiPACKED 两个研究;"Adi Katz 2023 缓存投毒"与"Adnan Khan Worm 2024"两处无法核验的引用按可核验来源改写(补 The Monsters in Your Build Cache 与 Cacheract 链接,删除 404 的 Horizon3 链接);tasrieit 与 reddit 移出"官方文档"小节,新增"第三方博客与社区讨论(非官方来源)"小节;全部记入不确定点⑨。
52026 年事件错放在 2025 年阶段GhostAction 第二波(2026-08-31~09-30)移入阶段五,并补入核验所得的第三波(2026-10-08~09);阶段总览表第 4/5 行、横轴"近年重大安全事件"行、2.6 交叉引用同步更新;阶段四驱动因素补跨章指引。
6关键数字无出处、违反自定标注方法"2.3 万仓库"补 StepSecurity 原文口径("used in over 23,000 repositories",直接抓取核验)并在正文标注;"3.9%"改标"Wiz 研究的二手转引"并新增不确定点②,同时在参考来源新增两个转引来源链接。
7结论性断言缺乏文本内支撑① secret scanning 付费口径改为"公共仓库免费自动启用;组织私有/内部仓库需 GitHub Secret Protection 付费加购"并补官方文档链接(直接抓取核验);② "唯一三层齐备"补判定口径(官方原生集成 vs 第三方 marketplace action);③ Immutable Releases"普及"改"开始被采用"并注明证据面;④ "CISA 响应证明政府级共识"改为与警报内容匹配的表述(警报缓解建议为审计/轮换/更新,未背书锁文件),CISA 警报内容经直接抓取核验。
8止步于"做什么"、缺"怎么做";规模混杂变量未承认新增 3.3 落地路径:盘点命令(pull_request_target 使用面、SHA 覆盖率、evaluate 影子模式影响预览)、12-02 强制后果与豁免(事件策略白名单 + workflow 文件定向)、锁文件启用方式/能力边界/存量仓库暂时做不到的原因、zizmor/Harden-Runner/Scorecard 三工具上手路径与推荐落地次序;洞察一末尾补"(事故更少部分也因其生态规模更小,见洞察二)"。

思考题(读完后想一想,参考答案可展开)

  1. 报告贯穿全文的核心论点是什么?「便利优先 → 被攻击教会 → 默认收紧」这条曲线在 GitHub Actions 八年历史中如何具体展开?
    参考答案

    八年安全史是「便利优先→被攻击教会→默认收紧」:2018 年留下默认读写 token、pull_request_target 逃生门、可改写标签三大隐患,被 Codecov、tj-actions、GhostAction 逐次击穿;2023 年 token 默认只读、2026 年执行策略与锁文件 GA,完成「用户开关」到「平台默认」翻转。深层判断:能力不缺,缺的是默认值与存量习惯。

  2. 在 Fork PR 隔离这一分歧最大的维度上,GitHub、GitLab、Bitbucket/Buildkite 分别代表哪种设计哲学?各自在安全与功能之间做了什么取舍?
    参考答案

    GitHub「默认可用但收权+逃生门」:fork PR 不发 secrets、首次贡献需审批,但 pull_request_target 自带 secrets 与写权限,成事故温床;GitLab 在 fork 上下文运行流水线,protected 变量不可达;Bitbucket 默认禁用最安全,但可用性×安全的综合体验 GitHub/GitLab 更好。

  3. 报告承认了哪些尚未解决的风险与自身的局限?(提示:存量习惯、锁文件的能力边界、数字核验)
    参考答案

    存量习惯没跟上:全量 SHA 钉扎仓库仅约 3.9%(二手转引),GhostAction 2026-10 第三波仍波及 3 万+仓库/约 1900 账号;锁文件有边界——不覆盖可复用工作流、不管输入参数/secrets/runner 镜像,需逐仓库接入,存量仓库「暂时做不到」。报告自身:3.9%、GitLab 定价等未核验或为二手转引,均列入文末不确定点。

  4. 对个人开发者,报告按优先级给出的行动清单是什么?围绕 2026-12-02 的强制节点,具体建议怎么做?
    参考答案

    ①12-02 前盘点 pull_request_target:能改 pull_request+workflow_run 就改,保留的走白名单+evaluate 影子预览;②Action 优先锁文件,否则钉 40 位完整 SHA;③org 级 token 默认只读、按 job 提权;④OIDC 替代长期 secrets;⑤自托管 runner 勿绑公共仓库;⑥zizmor/Scorecard 自评。

← 资料库今日播报 →