GitHub Actions 在缓存 Miri 输出时泄露秘密
摘要
Miri,一个 Rust 工具,在目标目录中存储所有环境变量,当在 GitHub Actions 中缓存时,可能将秘密泄露给拉取请求。Rust 团队已实施修复,仅保留特定变量,并建议用户检查他们的 CI 设置以查找漏洞。
<p><a href="https://lobste.rs/s/acz9kk/github_actions_leaking_secrets_when_miri">评论</a></p>
查看缓存全文
缓存时间: 2026/09/22 22:41
# GitHub Actions 缓存 Miri 输出时可能泄露密钥 | Rust 官方博客
来源:https://blog.rust-lang.org/2026/09/21/github-actions-leaking-secrets-when-miri-output-is-cached/
Rust 安全响应团队收到通知:Miri 会将所有环境变量存储至 `target/` 目录,导致密钥可能通过缓存持久化。
这本身虽不直接构成漏洞,但与 GitHub Actions 的缓存机制结合后,可能导致密钥被拉取请求(PR)访问。
## 问题概述
GitHub Actions 支持跨运行缓存目录。典型配置中,`main` 分支(及其他分支)的 CI 运行可*写入*缓存,而 PR 只能*读取*缓存(防止缓存污染)。Rust 项目常通过缓存 `cargo install` 生成的二进制文件或 `target/` 目录内容来加速 CI。
PR 的 CI 运行可由任何有权向仓库提交 PR 的人员触发。GitHub 要求首次 PR 需维护者批准,但后续 PR 的每次推送都会重新运行 CI。曾成功合并过代码的用户可触发 CI 运行,从缓存的 `target/` 目录中提取信息,再通过推送第二次提交至 PR 来掩盖痕迹。
GitHub 界面有时会隐藏被覆盖的提交记录,使得此类攻击更难被发现。CI 运行日志和被覆盖的提交记录也会在数月后删除。
当调用 `cargo miri` 时,Miri 需要在多次运行间保留与构建相关的环境变量[^1]。当前实现方式是将*所有*环境变量存储至 `target/` 目录。当 `target/` 被缓存时,这些数据自然会随之持久化。
若环境中存在密钥,攻击者现在可通过缓存访问这些 PR。
## 我们的修复方案
我们的[短期修复方案](https://github.com/rust-lang/miri/pull/5337)是让 Miri 仅保留 `CARGO_*` 环境变量(排除 `CARGO_*_TOKEN`)和 `OUT_DIR`。长远来看,Miri 和 Cargo 可能会设计更优的方式来向 Miri 传递相关环境变量列表。请注意此补丁可能尚未发布至 nightly 版本。
我们还对 GitHub 仓库进行了生态扫描,发现 1 个仓库存在此问题,7 个仓库虽未发现漏洞但需保持谨慎。我们已联系相关维护者进行通知。
## 我是否受影响?
我们的扫描可能存在遗漏,因此建议所有使用 Miri 的用户检查自己的 GitHub Actions 配置。
若您符合以下条件,则可能存在风险:
- 在 CI 中运行 `cargo miri`
- 运行 `cargo miri` 的步骤通过以下方式获得[密钥访问权限](https://docs.github.com/en/actions/how-tos/write-workflows/choose-what-workflows-do/use-secrets#using-secrets-in-a-workflow):
- 作为环境变量直接传入该步骤
- 在工作流的 `env` 中设置
- 通过之前步骤的环境变量传递持久化
- 使用的工作流缓存了 `target` 目录(通常通过 [`actions/cache`](https://github.com/actions/cache) 或 [`swatinem/rust-cache`](https://github.com/swatinem/rust-cache) 实现)
- 缓存可被 PR 访问(常见且通常是预期用途)
临时修复方案包括:
- 禁用该任务的缓存
- 将密钥作用域限制在未调用 Miri 的步骤中
- 暂时禁用 Miri
修复后请[清除缓存](https://docs.github.com/en/actions/how-tos/manage-workflow-runs/manage-caches#deleting-cache-entries)。建议轮换可能泄露的密钥。
即将发布的 nightly 版本(2026-09-22)中的 Miri 将不再存在此问题。
**即使不使用 Miri**,也请确保可向公共缓存写入的任务无法访问密钥。许多工具未对密钥做特殊处理,默认假设整个环境变量可写入文件系统。
## 威胁模型
我们认为缓存容易被密钥污染是一种不良实践。
若缓存 `target/` 目录,应确保创建该目录的进程(所有调用 `cargo` 的操作)无法获取密钥。标准 `cargo` 构建/测试子命令通常不需要密钥或令牌[^2],因此重点在于避免将密钥作为环境变量暴露给整个任务。
Cargo/Miri/Rust 不保证环境变量不会被复制至 `target/` 目录。尽管我们出于谨慎将其视为安全问题进行修补,但一般情况下不应依赖此特性。除官方 Rust 工具外,构建脚本也可能将环境信息存储到编译产物中。
## 致谢
感谢 OpenAI 的 [Predrag Gruevski](https://github.com/obi1kenobi) 向我们报告此问题。此外,生态扫描使用了 OpenAI 捐赠的 Codex 访问权限和额度,特此致谢。
问题分类与修复由 Manish Goregaokar、Ralf Jung、Ben Kimock、Weihang Lo、Jacob Finkelman、Walter Pearce、Josh Stone 和 Mark Rousskov 完成。
[^1]: 由于复杂原因,`cargo miri` 会多次调用 Miri [↩](https://blog.rust-lang.org/2026/09/21/github-actions-leaking-secrets-when-miri-output-is-cached/#fr-1-1)
[^2]: 理论上构建脚本可能通过网络读取触发此场景 [↩](https://blog.rust-lang.org/2026/09/21/github-actions-leaking-secrets-when-miri-output-is-cached/#fr-2-1)
相似文章
Anthropic、Google 和 OpenAI 自研编程代理的 GitHub Actions 默认配置均易受相同远程代码执行漏洞攻击
安全研究人员发现 Anthropic 的 Claude Code、Google 的 Gemini CLI 和 OpenAI 的 Codex 的默认 GitHub Actions 配置存在严重漏洞,攻击者可通过未经验证的 issue 执行远程代码。Google ADK 仓库中发现的一个相关权限提升缺陷,进一步揭示了这些 AI 代理 CI/CD 架构中系统性的薄弱环节。
GitLost:我们诱骗GitHub的AI代理泄露私有仓库
Noma Labs发现GitHub的Agentic Workflows中存在一个严重的提示注入漏洞,允许未经身份验证的攻击者通过在同一组织的公共仓库中发布精心构造的GitHub Issue,从私有仓库中窃取数据。
Bun Rust 重写:"代码库未通过基本 Miri 检查,在安全 Rust 中允许未定义行为"
Bun 的 Rust 重写未通过基本 Miri 检查,在安全 Rust 中导致未定义行为,引发了严重的安全担忧。
GitHub Actions 中 GitHub_TOKEN 在日志中泄露的问题
GitHub Actions 中的一个安全漏洞导致 GitHub_TOKEN 在日志中泄露,可能暴露凭据。
Grok Build CLI 会上传你整个仓库——包括完整 git 历史记录和 .env 密钥——到 xAI 的云端,而选择退出机制也无法阻止该行为(基于抓包分析)
一项安全分析发现,Grok Build CLI 工具会上传整个仓库,包括完整的 git 历史记录和 .env 密钥,到 xAI 的云端,并且提供的退出选择机制并未实际阻止该行为。