Branch Protection Bypass
Description
Workflows that auto-approve or auto-merge pull requests undermine GitHub branch protection: they short-circuit required reviewers, status checks, and manual merges. If an attacker compromises CI, or if a bug slips in, code can flow to protected branches without human oversight, voiding the controls branch protection is meant to provide. 1
Vulnerable Instance
- Workflow triggers on
pull_requestorpull_request_target. - Uses an action (e.g.,
peter-evans/enable-pull-request-merge) or CLI command (gh pr merge --auto) that approves/merges PRs automatically. 2 - Runs with default
GITHUB_TOKENwrite permissions, so the auto-merge succeeds even when branch protection expects reviewers.
name: Auto Merge Dangerous
on:
pull_request:
branches: [ main ]
jobs:
auto-approve-and-merge:
permissions: write-all
runs-on: ubuntu-latest
steps:
- name: Auto approve PR
run: gh pr review "$PR_URL" --approve
env:
PR_URL: ${{ github.event.pull_request.html_url }}
- name: Auto merge PR
uses: peter-evans/enable-pull-request-merge@v3
with:
token: ${{ secrets.GITHUB_TOKEN }}
merge_method: squashMitigation Strategies
- Remove automation that bypasses reviewers
Delete auto-approval/merge steps or replace them with manual review workflows (workflow_runplus approval gates). - Enforce branch protection in GitHub settings
Require at least one review, enable “Require status checks to pass,” and block force pushes. - Restrict workflow permissions
Setpermissions: { contents: read }by default and elevate only in dedicated release workflows reviewed by humans. - Add reviewer confirmation steps
Useworkflow_dispatchwith required inputs or GitHub’s built-in review system so humans must acknowledge the change. - Monitor for bypass keywords
Periodically scan workflows forauto-approve,auto-merge,gh pr review,gh pr merge, or similar commands.
Secure Version
name: Lint & Gate
on:
pull_request:
branches: [ main ]
jobs:
- auto-approve-and-merge:
- permissions: write-all
+ checks:
+ permissions:
+ contents: read
+ pull-requests: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: npm test
- - name: Auto approve PR
- run: gh pr review "$PR_URL" --approve
- env:
- PR_URL: ${{ github.event.pull_request.html_url }}
- - name: Auto merge PR
- uses: peter-evans/enable-pull-request-merge@v3
- with:
- token: ${{ secrets.GITHUB_TOKEN }}
- merge_method: squash
+ require-review:
+ needs: checks
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ steps:
+ - name: Notify reviewers
+ run: echo "All checks passed—waiting for human approval."
Impact
| Dimension | Severity | Notes |
|---|---|---|
| Likelihood | Auto-merge helpers are common in CI templates, especially for dependency updates. | |
| Risk | Bypassing branch protection enables unreviewed code (or attacker payloads) to land on protected branches. | |
| Blast radius | Compromised main/default branches impact every downstream deployment, release, or package built from them. |
References
- GitHub Docs, “Managing a branch protection rule,” https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule 1
- GitHub Docs, “Automatically merging a pull request,” https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request 2
GitHub Docs, “Managing a branch protection rule,” https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/defining-the-mergeability-of-pull-requests/managing-a-branch-protection-rule ↩︎ ↩︎
GitHub Docs, “Automatically merging a pull request,” https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request ↩︎ ↩︎