# Gain write permission of repositories with a bug in GitHub Actions

GitHub Actions leaked the target repo's GITHUB_TOKEN to pull_request jobs from forks, letting an unauthenticated attacker force-push to main.

- Payout: $25,000
- Severity: critical
- Program: GitHub
- Credited: tyage
- Disclosed: 2021-04-02
- Write-up quality: 8/10
- Original: https://blog.tyage.net/posts/2021-04-02-improper-access-control-github-workflow/
- Library page: https://bugbountylibrary.com/r/blog%3Ablog-tyage-net-posts-2021-04-02-improper-access-control-github-workflow
- Tags: domain:oss impact:integrity impact:privesc kind:bounty platform:blog sev:critical tech:github-actions technique:chained vuln:access-control vuln:auth-bypass

**Target:** GitHub Actions pull_request workflow token
**Root cause:** GITHUB_TOKEN for the base repository was shared with jobs triggered by pull_request events from forked repos, so untrusted fork code ran with the victim repo's write-scoped token.
**Steps:**
1. Victim repo has any workflow in `.github/workflows`; attacker has no commit rights.
2. Attacker forks repo and replaces workflow with `on: [pull_request]` job that checks out, commits a file, and pushes via `https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}` to `HEAD:refs/heads/main`.
3. Attacker opens a pull request to the parent repo and waits.
4. Workflow runs with victim's token; force-push modifies main branch.
**How found:** Observed DDoS abuse where attackers forked repos and ran malicious workflows via pull_request events to bypass resource limits; hypothesized that if compute resources were shared for PR jobs, the GITHUB_TOKEN might also be shared, then tested by sending a PR and waiting.
**Exploitation:** Attacker forks the target, swaps the workflow file to a pull_request-triggered job that uses the injected GITHUB_TOKEN to force-push to refs/heads/main, then opens a PR; the job executes with the base repo's write token and commits attacker content to the protected-less main branch.
**Insight:** When a CI system runs untrusted fork/PR code, check whether privileged context (tokens, secrets, resource quotas) from the base repo leaks into that job; a shared-resource observation is a strong signal to test shared credentials.
