CI Token权限泄露

周末没有我719 新手 1天前 730 浏览 0 点赞 约 2 分钟

在公司推行 CI/CD 安全标准的时候,最让人头疼的不是没工具,而是工具报的警太“片面”。前段时间我在维护 mcpscan(一个扫描 MCP 配置和 GitHub Actions 工作流的静态扫描器)时就踩了个坑,原本以为写好了一条规则就能封堵 workflow_run 的权限漏洞,结果上线第二天发现,它只能抓到一半的 Bug。

CI Token权限泄露

很多开发者对 pull_request_target 的风险心知肚明,但 workflow_run 这种“静默漏洞”更容易被忽视。它的逻辑是:当另一个工作流结束时触发,且始终在默认分支运行,持有仓库的正常 Token。如果触发它的那个前置工作流可以被 Fork 的 PR 触发,那么一个不受信任的事件就被传递给了一个拥有高权限的 Job。

这种特权 Token 的滥用路径其实有两条,而我最初的规则只覆盖了其中一种:

  • 代码检出滥用: 直接检出 github.event.workflow_run.head_sha.head_branch。此时风险点在提交的代码本身。

  • 产物(Artifact)滥用: 下载前置运行产生的 Artifact 并直接执行。此时风险点在构建输出物。
  • 我最初在 v0.14.0 版本中定义的 MCP019 规则,不仅只盯着 Artifact 下载,还加了一个条件:只有在工作流没有定义 permissions: 限制块时才报警。

    这种设计逻辑在表面上看起来提高了“信号质量”,但在实际工程中却制造了巨大的盲区。首先,直接检出 SHA 的路径被完全忽略了;其次,只要开发者写了任何一个 permissions 限制(哪怕范围很宽),规则就会认为该漏洞已处理。但事实上,只要不受信任的代码在特权 Job 中运行,缩小 Token 范围并不能从根本上消除执行风险。

    来看一个典型的漏洞配置示例:

    name: post-build
    on:
    workflow_run:
    workflows: [Build]
    types: [completed]
    jobs:
    post:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/download-artifact@v4
    with:
    name: build-output
    run-id: ${{ github.event.workflow_run.id }}
    github-token: ${{ secrets.GITHUB_TOKEN }}
    - name: Run whatever the triggering build produced
    run: ./build-output/script.sh

    在这个例子中,最后一行 run: ./build-output/script.sh 就是致命伤。Fork 仓库的构建步骤产生了什么,这里就执行什么,完全没有校验。

    为了解决这个问题,我在 v0.15.0 中将规则进行了拆分,不再让它们相互依赖。对于数据工程师或 DevOps 来说,这种 DX(开发体验)的教训就是:安全规则不能过度追求“精准”而通过增加耦合条件来降低误报,否则漏报带来的代价远高于处理几次误报。

    工作流AI落地devopsopensourcesecurity

    全部回复 (4)

    向量检索中784 新手 1天前
    确实,之前被这个坑过,权限给宽了直接被刷库(心在滴血)。
    0 回复
    调参调到秃602 新手 1天前
    @向量检索中784 没做最小化权限真的太险,我之前被刷过一次,整周都在补窟窿。你当时怎么止损的?
    0 回复
    B
    bug不是我的 新手 1天前
    建议直接上 OIDC 临时凭证,比死磕权限配置稳多了。
    0 回复
    多模态玩家386 新手 1天前
    没用动态 Token 没意义,你这规则能绕过环境变量注入吗?
    0 回复

    发表回复

    支持 Markdown 格式