配了三年 GitHub Actions,今天才发现 runner 根本不是个临时容器——它已经是需要被保护的生产端点了

2025 年 3 月,tj-actions/changed-files 被篡改了版本标签,23000 个仓库的 runner 内存里的 secret 全被打进了 Actions 日志。攻击者用的方法并不高级:先拿下 action 版本标签,再等 runner 跑起来,然后用一行 curl 把内存里的东西发出去。

事后的复盘报告写了十几篇,都在说”OIDC 上了没””action SHA 锁了没”。几乎没人提一个更基础的问题:那个 runner 到底能访问哪些网络地址?

答案是:所有地址。没有任何限制。

runner 一直是敞开的出口

GitHub Actions 的安全模型在”进来”这一侧已经很完善了。OIDC 令牌免去了存储长期云凭证的需要,GITHUB_TOKEN 可以按最小权限 scoping,action 版本可以用 SHA256 精确锁定。这些控制管的是”谁能触发这个 workflow”和”跑什么代码”,但从来没人管过”跑起来的代码能打给谁”。

runner 就是一个普通的虚拟机,一旦代码在里面执行,它就可以访问互联网上的任意主机。OIDC 能证明这个 runner 是你启动的,但不能证明它应该访问哪个外部地址。

这和服务器安全的逻辑正好相反。我们花了很多力气把生产服务器放在 VPC 里面、限制入站规则、监控异常出站流量——但对 runner 这个”临时执行的服务器”却从来不问出口策略。两起真实攻击证明了这是真实存在的漏洞,不是理论上的:

2025 年 3 月 tj-actions 事件:攻击者篡改版本标签,恶意代码 dump runner 内存里所有 secret、PAT、云凭证。23,000 个仓库中招。

2026 年 3 月 Trivy/TeamPCP 事件:Aqua Security 的 Trivy 扫描器被攻破,SSH 密钥、AWS/GCP/Azure Token、Kubernetes Secrets、Docker 配置全被抽走。攻击链蔓延到 Checkmarx、LiteLLM 和 60+ npm 包。10,000+ CI/CD 工作流受影响。

两起事件的根因完全相同:恶意代码进了 runner 之后,想打给谁就打给谁。

GitHub Native Egress Firewall:跑在 VM 外面的防火墙

GitHub 在 2026 年 3 月发布了完整的安全路线图,其中最关键的一件就是 Native Egress Firewall。它的架构和之前所有安全措施的根本区别在于:它在 runner 虚拟机外部运行

之前社区最好的方案是 StepSecurity Harden-Runner,跑在 runner 内部、在进程层面拦截网络调用。拿到 root 权限后理论上可以绕过它。

GitHub 的方案是跑在网络基础设施层面。防火墙在 runner VM 和互联网之间,对所有出站 DNS 查询和 HTTP/HTTPS 请求做 L7 检查。runner 里的代码拿到 root 也接触不到防火墙——它不在 VM 里面。

启用方式就是改一行 runner 标签:

jobs:
  build:
    runs-on: ubuntu-24.04-firewall
    steps:
      - uses: actions/checkout@v4
      - run: npm ci && npm test

没有 action 要装,没有 secret 要配,没有 workflow 结构要改。ubuntu-24.04-firewall 镜像是标准 Ubuntu 24.04 加了一层网络基础设施级别的监控。技术预览阶段是纯审计模式:记录所有出站请求并关联到对应的 workflow run、job、step,但不做拦截。性能代价约 15-20% job 运行时增加。

TLS 检查: ephemeral certificate per run

L7 过滤要按域名做 allowlist,光看 IP 不够用。防火墙在出口边界终止 TLS、检查、重新加密发到目标。每个 workflow run 用一个临时证书,run 结束立即销毁。没有持久解密能力——这是企业合规最在意的地方,解密能力是 ephemeral 的,policy 才是持久资产。

三件套:各打断攻击链的一个节点

GitHub 2026 安全路线图实际上是一套纵深防御,三件工具各针对攻击链的一个环节:

Lockfile(依赖锁定)——把 action 及其所有传递依赖锁定到 SHA256 哈希,hash 不匹配则 job 不跑。这一环阻止”篡改版本标签拉取恶意代码”这条上游路径。

Scoped Secrets(范围化凭证)——把 secret 绑定到特定执行上下文(分支、环境、workflow 身份、可信 reusable workflow)。即使某一步被突破,爆炸半径也只限于这一步实际授权的范围。

Egress Firewall(出口防火墙)——即使恶意代码跑了进来、找到了 secret,也无法把它传出去。出口被封堵了。

Lockfile 阻止坏代码运行。Scoped secrets 限制代码能找到的东西。Egress firewall 阻止代码把找到的东西送出去。三件套各自针对攻击链的不同节点,合在一起才是完整的防御。

现在该做什么

技术预览阶段纯审计,enforcement 模式(allowlist + 阻断)公开预览预计 Q3-Q4 2026。这意味着现在注册的用户会积累真实流量数据——你的 CI/CD 实际连接了哪些域名、哪些 IP 范围、哪些 HTTP 方法。等 enforcement 来的时候,直接切换。

不注册的人面临冷启动:在 enforcement 模式下,未在 allowlist 的目标全部阻断,需要一次性把整个 CI/CD 依赖的所有外部地址全部摸清楚。

三行 YAML,一个 runner 标签。这是目前 CI/CD 安全里性价比最高的动作。别等。

评论区

0 条评论

登录后可评论。