Skip to content

Commit a65ebe2

Browse files
committed
gh cache
1 parent df0aaa9 commit a65ebe2

2 files changed

Lines changed: 16 additions & 1 deletion

File tree

src/pentesting-ci-cd/github-security/abusing-github-actions/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ GitHub exposes a cross-workflow cache that is keyed only by the string you suppl
481481
- Cache entries are shared across workflows and branches whenever the `key` or `restore-keys` match. GitHub does not scope them to trust levels.
482482
- Saving to the cache is allowed even when the job supposedly has read-only repository permissions, so “safe” workflows can still poison high-trust caches.
483483
- Official actions (`setup-node`, `setup-python`, dependency caches, etc.) frequently reuse deterministic keys, so identifying the correct key is trivial once the workflow file is public.
484+
- Restores are just zstd tarball extractions with no integrity checks, so poisoned caches can overwrite scripts, `package.json`, or other files under the restore path.
484485

485486
**Mitigations**
486487

@@ -806,4 +807,3 @@ An organization in GitHub is very proactive in reporting accounts to GitHub. All
806807
{{#include ../../../banners/hacktricks-training.md}}
807808

808809

809-

src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-cache-poisoning.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,10 @@ The GitHub Actions cache is global to a repository. Any workflow that knows a ca
1010

1111
- `actions/cache` exposes both restore and save operations (`actions/cache@v4`, `actions/cache/save@v4`, `actions/cache/restore@v4`). The save call is allowed for any job except truly untrusted `pull_request` workflows triggered from forks.
1212
- Cache entries are identified solely by the `key`. Broad `restore-keys` make it easy to inject payloads because the attacker only needs to collide with a prefix.
13+
- Cache keys and versions are client-specified values; the cache service does not validate that a key/version matches a trusted workflow or cache path.
14+
- The cache server URL + runtime token are long-lived relative to the workflow (historically ~6 hours, now ~90 minutes) and are not user-revocable. As of late 2024 GitHub blocks cache writes after the originating job completes, so attackers must write while the job is still running or pre-poison future keys.
1315
- The cached filesystem is restored verbatim. If the cache contains scripts or binaries that are executed later, the attacker controls that execution path.
16+
- The cache file itself is not validated on restore; it is just a zstd-compressed archive, so a poisoned entry can overwrite scripts, `package.json`, or other files under the restore path.
1417

1518
## Example exploitation chain
1619

@@ -41,6 +44,16 @@ steps:
4144
4245
The second job now runs attacker-controlled code while holding release credentials (PyPI tokens, PATs, cloud deploy keys, etc.).
4346
47+
## Poisoning mechanics
48+
49+
GitHub Actions cache entries are typically zstd-compressed tar archives. You can craft one locally and upload it to the cache:
50+
51+
```bash
52+
tar --zstd -cf poisoned_cache.tzstd cache/contents/here
53+
```
54+
55+
On a cache hit, the restore action will extract the archive as-is. If the cache path includes scripts or config files that are executed later (build tooling, `action.yml`, `package.json`, etc.), you can overwrite them to gain execution.
56+
4457
## Practical exploitation tips
4558

4659
- Target workflows triggered by `pull_request_target`, `issue_comment`, or bot commands that still save caches; GitHub lets them overwrite repository-wide keys even when the runner only has read access to the repo.
@@ -50,5 +63,7 @@ The second job now runs attacker-controlled code while holding release credentia
5063
## References
5164

5265
- [A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes](https://words.filippo.io/compromise-survey/)
66+
- [The Monsters in Your Build Cache: GitHub Actions Cache Poisoning](http://adnanthekhan.com/2024/05/06/the-monsters-in-your-build-cache-github-actions-cache-poisoning/)
67+
- [ActionsCacheBlasting (deprecated, Cache V2) / Cacheract](https://github.com/AdnaneKhan/ActionsCacheBlasting)
5368

5469
{{#include ../../../banners/hacktricks-training.md}}

0 commit comments

Comments
 (0)