机密泄露并不总是与糟糕的代码或易受攻击的库有关。有时,它取决于我们在 CI 运行期间如何管理机密,而 CVE-2025-30066 就是一个典型的例子,说明了这种情况如何发生。GitHub Action tj-actions/changed-files 广泛用于检测以下项目中的更改文件: pull requests,成为了秘密泄露的无声渠道。以下是发生的事情以及如何锁定你的 CI/CD 秘密 pipeline.
CVE-2025-30066 发生了什么?
2025 年 XNUMX 月中旬,tj-actions/changed-files 遭到入侵。 攻击者重写了现有的版本标签(最高到 v45.0.7),以指向恶意 commit。这在开发人员没有注意到的情况下改变了 Action 的行为;没有发布新版本,只是隐形的标签篡改。
该有效载荷简单易懂,但非常危险:它提取了一个远程Base64编码的Python脚本,该脚本会扫描运行器内存中的凭证,并将其转储到日志中或泄露出去。这并非tj-actions/changed-files中的逻辑代码缺陷,而是滥用了该可重用操作在CI工作流中泄露机密信息的方式。CVE-2025-30066并非缓冲区溢出漏洞,而是CI设计缺陷导致机密信息泄露。
影响:任何使用受影响版本的 tj‑actions/changed‑files 的 repo 都存在机密泄露的风险,尤其是在文件模式或 CI 输出中不安全地处理敏感令牌或文件时。
为什么这会影响依赖可重用操作的工作流程
DevSecOps 工作流 严重依赖 tj‑actions/changed‑files 来:
- 自动化 pull request 检查
- 识别特定路径中已更改的文件
- 避免冗余 CI 作业
但这些工作流程经常忽略一件事:通配符模式可能包含敏感数据。开发人员默认 tj-actions/changed-files 的行为是安全的。然而,如果你使用通配符 配置/** 并且秘密存储在 配置/secrets.env,你刚刚将一个机密文件添加到了 CI 输出或日志中。这不是 Action 中的 bug,而是一个 CI/CD 设计缺陷导致机密泄露。CVE-2025-30066 就是一个明显的例子。
机密泄露是如何发生的(漏洞分析)
让我们来剖析一下 CVE-2025-30066 背后的核心故障:
- 通配模式,如 **/*.环境变量 无意中匹配的秘密文件
- tj‑actions/changed‑files 将这些机密视为已更改的文件
- 机密最终出现在步骤输出、日志或下游作业中
发生这种情况的原因是机密存储在版本控制的路径中(这不是个好主意),而且 CI 配置没有明确将它们排除在通配符之外(这也是个坏主意)。所以这不是代码错误,而是 CI 设计卫生不良导致机密通过 tj-actions/changed-files 输出泄露。
实用漏洞利用路径:从 CI 工作到凭证暴露
导致机密信息通过 tj-actions/changed-files 泄露的 CI 设置示例:
yaml
jobs:
detect_changes:
runs‑on: ubuntu‑latest
steps:
‑ uses: actions/checkout@v3
‑ name: Check changed files
id: changed
uses: tj‑actions/changed‑files@v45
with:
files: configs/**
If 配置/secrets.env 已更改:
- 它被 tj‑actions/changed‑files 标记
- 它被纳入 步骤.更改.输出.所有更改的文件
- 后续步骤将其记录下来或传递给脚本,从而泄露机密
此次泄露的起因是 CI 逻辑将机密信息视为普通文件。机密信息泄露的起因并非缓冲区溢出,而是 CI 设计缺陷导致的 tj-actions/changed-files 的误用。
传播发生在如下输出中:
yaml
‑ name: Use changed file list
run: echo "Changed files: ${{ steps.changed.outputs.all_changed_files }}"
If secrets.env 在该列表中,其文件名以及可能的内容可能会出现在构建日志中。即使是像以下这样的条件逻辑:
yaml
if: contains(steps.changed.outputs.all_changed_files, 'secrets.env')
可能会暴露敏感文物。这是一个 CI/CD 设计失败导致机密泄露,而不是 Action 代码中的缺陷。
如何安全地使用可重复使用的工作流程并防止泄漏
您无需放弃 tj-actions/changed-files。您应该以“机密优先”的心态使用可重复使用的 Actions:
机密处理最佳实践
- 永远不要对秘密进行版本控制
- 避免使用与敏感路径匹配的 glob 模式
- 使用基于环境的秘密(GITHUB_ENV、vaults、GitHub Secrets)
CI/CD 配置 Guardrails
- 始终将操作固定到不可变的 SHA,而不是标签(切勿使用 @v45)
- 将 tj‑actions/changed‑files 输出视为受污染,对其进行清理或过滤
- 仅当已清理时才设置输出
⚠️ 不安全的例子:
yaml
jobs:
detect_changes:
runs‑on: ubuntu‑latest
steps:
‑ uses: actions/checkout@v3
‑ name: Detect all changes
id: changed
uses: tj‑actions/changed‑files@v45
with:
files: '**/*' # ⚠️ This glob includes secrets.env, which may leak credentials
以上正是秘密泄露和 CVE-2025-30066 背后的滥用行为。
安全替代方案:
yaml
jobs:
detect_changes:
runs‑on: ubuntu‑latest
steps:
‑ uses: actions/checkout@v3
‑ name: Detect non‑sensitive file changes
id: changed
uses: tj‑actions/changed‑files@<SHA> # pinned to SHA
with:
files: 'src/**'
files‑ignore: '**/secrets.env' # ⚠️ Excludes secret file
通过这样做,你可以避免 CI/CD 设计失败导致秘密通过 tj-actions/changed-files 泄露。
另外:
- 禁用或限制可能出现机密信息的日志记录
- 使用 GitHub 的秘密屏蔽功能
- 限制对构建日志和工件的访问
快速秘密安全 CI 使用清单
| 最佳实践 |
|---|
| 不要将机密存储在版本控制的文件中 |
| 使用 Vault 或 GitHub Secrets 作为凭证 |
| 始终将 tj‑actions/changed‑files 固定到不可变的 SHA |
| 过滤或清理 tj‑actions/changed‑files 的输出 |
| 切勿在 glob 模式中包含秘密路径 |
| 屏蔽或限制可能暴露敏感数据的日志 |
| 经常审核继承的 CI 配置 |
Xygeni 的作用:大规模 CI 机密执行
西吉尼 作保 CI/CD pipeline通过关注 现实世界中如何处理、使用和暴露秘密 DevOps 工作流程。这不仅仅是扫描代码;而是通过实时监控来执行机密管理最佳实践 pipeline 分析。
不安全输出使用检测
- 扫描 GitHub Actions 用于 回显、运行和输出,其中 ${{ steps.*.outputs.* }} 可能包含敏感值
- 识别机密信息被直接、有意或错误引用或打印的情况
泄露机密监控
- 检测日志和步骤输出中的高熵值(API 密钥、令牌)
- 当机密出现在 pipeline 日志,即使下游被屏蔽
操作使用配置错误
- 跟踪所有 GitHub Actions pipeline检测受损版本的使用情况(例如 tj-actions/更改的文件@v45)
- 审计包含潜在机密的文件匹配模式,例如 **/*.env、*.key 或 .env.*
基于策略的CI Guardrails
- 强制第三方操作使用 SHA 固定
- 阻止使用可能将机密信息扫入日志的不安全文件
- 可防止 pipelines 将敏感值作为工作流输出的一部分
通过将工作流程视为威胁面的一部分,Xygeni 确保秘密卫生不仅仅是一种最佳实践,而是一种内置防御。
结论:机密泄露可能始于简单的操作误用
CVE-2025-30066 不是一个库错误;它是一个 CI/CD tj-actions/changed-files 使用不当导致的设计失败。DevSecOps 团队应该吸取的教训:
- 将 CI 中的每个 glob/file 引用视为潜在的泄漏点
- 定期审核工作流程,防止意外泄露机密
- 使用安全保险库或环境机密,切勿将机密签入版本控制
- 清理或过滤所有工作流输出
- 记录敏感的工作流活动以保持可审计性
CI 是代码。工作流是代码。日志和输出也是代码。务必在每一步都保护好你的秘密,否则就有可能出现秘密泄露的情况,而这种泄露不需要黑客,只需要一个坏人。 CI/CD 设计选择。





