Proper Github Workflow Security
Base Metric | score | severity |
---|---|---|
overall | 0 | none |
Type: Investigated
Status: fixed
Reporting Date: 2023.04.05
The github action workflows were checked for usage of risky patterns,
handling community contributions where workflows are triggered with
pull_request
and were found to be properly implemented.
Description
The initial check of the .workflows
directory indicated that some workflows
are run as soon as a pull request is created.
We consulted the github documentation for the usage of pull_request
and found the
usage to be without immediate risks, as only pull_request_target
with an explicit
checkout of an untrusted pull request directly exposes the GITHUB_TOKEN
1
by default. The current instance does not facilitate the vulnerable combination.
Due to the dangers inherent to automatic processing of PRs, GitHub’s standard pull_request workflow trigger by default prevents write permissions and secrets access to the target repository. However, in some scenarios such access is needed to properly process the PR. To this end the pull_request_target workflow trigger was introduced. 2
Proof of Concept
To simplify the understanding a small proof of concept was created. The following steps verify that secrets configured in the repository are not leaked when a PR triggers a specific workflow file, that has been modified by a potential attacker.
Create initial workflow .github/workflow/leaky.yml
file on main
name: leaky secret test
on:
pull_request:
branches: [ "main" ]
paths:
- ".github/workflows/leaky.yml"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: Run a one-line script
run: echo Hello, world!
Create PR with following changes
name: leaky secret test
on:
pull_request:
branches: [ "main" ]
paths:
- ".github/workflows/leaky.yml"
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: Run a one-line script
run: |
printf "Got secret: '%s'\n" ${{ secrets.SUPER_SECRET_VALUE }}
The action is being run with following output
Run printf "Got secret: '%s'\n" ***
printf "Got secret: '%s'\n" ***
shell: /usr/bin/bash -e {0}
Got secret: '***'