Coordinated Disclosure Timeline
- 2024-11-07: Reported through MSRC.
- 2024-11-08: Fixed in commit d77384f.
Summary
The pr-website-deploy-comment
workflow is vulnerable to Poisoned Pipeline Execution (PPE).
Project
Microsoft FluentUI
Tested Version
Latest commit at the time of reporting.
Details
Code Injection in pr-website-deploy-comment.yml
workflow (GHSL-2024-327
)
The pr-website-deploy-comment.yml
workflow gets triggered when the workflow ‘PR Website Deploy’ finishes successfully:
name: PR Website Deploy | Comment on PR
on:
workflow_run:
workflows: ["PR Website Deploy"]
types:
- completed
...
jobs:
deploy:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.event == 'pull_request' && github.event.workflow_run.conclusion == 'success' }}
...
The workflow then downloads two artifacts generated by the triggering workflow and extracts the contents of pr.txt
into a step output variable called id
:
- name: Download WebSite artifacts
uses: actions/download-artifact@v4
with:
name: pr-website-artifacts
path: ./website
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- uses: actions/download-artifact@v4
with:
name: pr-number
path: ./results
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Load PR number
id: pr_number
run: echo "id=$(cat pr.txt)" >> $GITHUB_OUTPUT
working-directory: ./results
This step output variable is then interpolated into a bash script that gets executed:
- name: Load WEBSITE URL
id: website_url
run: echo "id=${{env.DEPLOY_HOST_URL}}pull/${{steps.pr_number.outputs.id}}/" >> $GITHUB_OUTPUT
A malicious actor could send a Pull Request and modify the triggering workflow to upload any arbitrary content to the pr.txt
file. Since the contents of this file are not validated and they get interpolated into a Bash script, the attacker will be able to get arbitrary code execution in the context of the deploy
job.
Similar injections affect other steps:
- name: Upload PR WebSite
uses: azure/cli@v2
env:
AZCOPY_AUTO_LOGIN_TYPE: 'AZCLI'
with:
azcliversion: latest
inlineScript: |
az storage blob upload-batch \
--destination '$web' \
--source ./website \
--account-name ${{ env.AZURE_STORAGE }} \
--destination-path pull/${{steps.pr_number.outputs.id}} \
--auth-mode login \
--overwrite
and
- name: Update PR deploy site GitHub status
uses: actions/github-script@v7
with:
script: |
const run = require('./.github/scripts/deploy-pr-site-status');
const config = { websiteUrl: '${{ needs.deploy.outputs.website_url }}', prId: '${{ needs.deploy.outputs.pr_number }}'};
await run({github,context,core,config});
Impact
The deploy
job has access to the AZURE_CLIENT_ID
, AZURE_TENANT_ID
and AZURE_SUBSCRIPTION_ID
secrets and, in addition, has id-token: write
permissions so an attacker would be able to fetch a JWT to log in into Azure CLI. Its not clear what permissions are granted to this token but it seems like, at least, it will have access to release a new version of the FluentUI web site (https://react.fluentui.dev/?path=/docs/concepts-introduction–docs) since this is what the workflow does. An attacker could use this to inject XSS or links pointing to malware in such website.
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-327
in any communication regarding this issue.