After reading the Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests blog post I digged deeper into the vulnerability and found that many maintainers fall into the same pitfall while remediating the Pwn Request vulnerability. This discovery led to 8 fix bypasses immideately and several later.
The bypass uses the fact that the pull_request_target
event runs workflows from a target branch (in contrast to most other events that always run workflows from the default branch). So by changing the target branch one can bypass a fix.
Consider the following scenario:
- A workflow with the Pwn Request vulnerability is committed to the default branch of a repository.
- Maintainers create new branches from the default branch. In this way vulnerability propogates to another branches.
- The vulnerability gets fixed in the default branch.
- However, the non-default branches still contain the vulnerability.
If a malicious user creates a pull request against a non-default branch in which the vulnerable workflow still exist, the vulnerable version of the workflow will be executed, not the fixed one. In this way the malicious user will bypass the fix.
Having a vulnerable workflow in a non-default branch is not always exploitable. When using the pull_request
and pull_request_target
events, one can configure a workflow to run only for pull requests that target specific branches using the branches
and branches-ignore
filters.
For example, the continuous-integration.yml workflow had a pwn request vulnerability (GHSL-2020-249). Maintainers applied the fix only to the default branch. However, the workflow runs only on pull requests to the master
and release-1.x
branches:
name: CI Workflow
on:
pull_request_target:
branches:
- master
- release-1.x
...
The vulnerability was fixed at master
and branches matching the release-1.x
pattern didn't contain the vulnerable workflow thus it was not possible to run the workflow by targeting another branch so it was not possible to bypass the fix.
Run setup-bypass-another-branch.sh
as the victim to create a repository with two branches. The default branch is safe while the other branch is unsafe.
You'll need gh installed to execute the
setup-bypass-another-branch.sh
script
TODO: write-up the proof of concept
The remediation is straightforward. When fixing the Pwn Request vulnerability either (1) fix it in all branches or (2) fix it in the default branch and delete all non-default branches that contain the vulnerable workflow.
Some repositories have a lot of branches and workflows so checking every branch and workflow manually would be at least tedious. I've created the bypass-another-branch.sh
script that goes through each branch and extracts unique workflow files.