Open
[Bug]-Actions runner 将 PR 正文文本拼接进 shell 脚本,提交者可控内容会被求值执行 #2226
Wang HengAdd on  14 days ago
Wang Heng
14 days ago Create

环境

  • GitCode Actions,runner 版本 0.0.4.10.version,镜像 ubuntu-latest
  • 发现日期:2026-09-01
  • 发现方式:非主动测试。排查一条与安全无关的流水线问题时,从构建日志中意外观察到

现象

Runner 执行 run: 步骤时,会把运行上下文(暴露为环境变量 __ATOMGIT_CONTEXT_DATA__)的内容以文本方式拼接进即将执行的 shell 脚本,而不是作为一个正确引用的环境变量传递给 bash。

该上下文包含 Pull Request 的 titlebody——由提交者完全控制的字段

因此,当某个 workflow 步骤在脚本里引用了这个变量,PR 正文中的 shell 元字符会被 bash 按语法解释,而不是当作数据处理。

日志证据

某步骤脚本中有一行形如 echo "$__ATOMGIT_CONTEXT_DATA__" | ... 的语句。该 PR 的正文里有若干处用 Markdown 反引号包起来的普通说明文字。构建日志随即出现:

/home/slave1/runner/workers/<...>/_temp/<uuid>.sh: line 8: 2026-08-30: command not found
/home/slave1/runner/workers/<...>/_temp/<uuid>.sh: line 8: main~3: command not found
/home/slave1/runner/workers/<...>/_temp/<uuid>.sh: line 8: head.sha: command not found
/home/slave1/runner/workers/<...>/_temp/<uuid>.sh: line 8: non_ff_passed: command not found

每一条都逐字对应 PR 正文中被反引号包围的内容。

同一份日志里另有一条 fatal: could not read Username for 'https://gitcode.com',对应正文里被反引号包围的一条 git 命令——它确实被执行了,只是因为 checkout 步骤已清除凭据而失败。

也就是说:这些字符串没有被当成数据打印,而是被 shell 当成命令求值了。报错中的 line 8 正指向脚本里引用该上下文的那一行。

影响

任何能对目标仓库发起 Pull Request 的人,只要该仓库某个 workflow 在 shell 步骤里引用了上述上下文变量,即可让自己控制的文本在构建机上以 runner 权限被求值。

需要评估的后续影响面:

  • 构建机在 checkout 阶段持有仓库凭据(日志中为 http.extraheader,步骤结束前才 Removing auth,在此之前存在凭据可用窗口)
  • 构建环境中可能存在为其他步骤准备的密钥与令牌
  • 构建机具备出站网络访问能力
  • 构建产物可被篡改

触发不需要仓库写权限,也不需要 PR 被合并——CI 在 PR 打开时即运行。

复现条件

  1. 仓库存在 on: pull_request 的 workflow
  2. 该 workflow 某个 run: 步骤在脚本中引用了 __ATOMGIT_CONTEXT_DATA__
  3. 提交者在 PR 正文或标题中放入含 shell 元字符的文本

满足以上条件时,日志中会出现这些文本被求值的痕迹。本报告不提供可直接使用的利用载荷。

建议的修复方向

根因是上下文数据以文本替换方式进入脚本,跨越了「数据」与「代码」的边界。

  1. 不要把上下文内容文本拼接进脚本。 通过环境变量传递,并确保赋值经过正确引用——例如写入 .env 文件后由 shell 读取,而不是拼接 export VAR=<原始内容>
  2. 隔离提交者可控字段。 titlebody、分支名、提交信息等应视为不可信输入,与 runner 自身元数据分开处理
  3. 回归测试建议:在 PR 标题与正文里放入 shell 元字符(反引号、$(...);、换行),确认日志中它们被原样输出而非求值

报告方已采取的缓解

我方 workflow 中已停止使用 $__ATOMGIT_CONTEXT_DATA__ 展开,改用 printenv __ATOMGIT_CONTEXT_DATA__ 取值,以避开文本替换路径。

此缓解仅对我方自己的 workflow 有效,不构成对该问题的修复

补充

如贵方有专门的安全响应渠道,我方乐意配合把细节转到私密渠道,并按贵方披露政策约定公开时间。此处提交是因为未找到公开的安全报告入口。

likedislike
AtomGit小助手
AtomGit小助手Collaborators
13 days ago Comments:

您好,感谢您的反馈,该问题目前已经反馈技术进行核实,感谢您的耐心等待。

likedislike
AtomGit小助手
AtomGit小助手Collaborators
11 days ago Comments:

感谢您的详细漏洞报告,我们已经将问题给到技术团队核实处理,现回复如下:

  1. __ATOMGIT_CONTEXT_DATA__属于内部调试用变量,并未对外文档公开,下个版本我们会移除该变量,相关业务数据请使用标准 atomgit 上下文对象获取。
  2. 针对 pull_request 事件场景,我们会对所有用户可控输入做审计校验;workflow 执行基于源分支 commitId 或者预合并代码运行,后续会落地对应的安全审核防护机制,防范恶意代码注入风险。
  3. 根因在于 runner 侧脚本拼接实现,我们正在修复该逻辑,避免不可信用户输入直接被 shell 解析执行。
likedislike