Remote code execution (RCE) via PR code checkout in GitHub Actions

Critical Risk Application Security
github-actionsyamlpull-request-targetrceci-cdsupply-chain

What it is

GitHub Actions workflows using the pull_request_target trigger combined with checking out pull request code create a critical security vulnerability. This configuration allows untrusted code from external contributors to execute with elevated privileges and access to repository secrets, potentially leading to secret exfiltration, repository compromise, and supply chain attacks.

â„šī¸ Configuration Fix

Configuration changes required - see explanation below.

💡 Explanation

â„šī¸ Configuration Fix

Configuration changes required - see explanation below.

💡 Explanation

â„šī¸ Configuration Fix

Configuration changes required - see explanation below.

💡 Explanation

Why it happens

GitHub Actions workflow: on: pull_request_target followed by actions/checkout@v3. pull_request_target runs with base repository secrets. Checking out PR code provides access. Attackers submit PRs with malicious workflow code. Combined with secrets, enables repository compromise.

Root causes

Using pull_request_target with Unsafe Code Checkout

GitHub Actions workflow: on: pull_request_target followed by actions/checkout@v3. pull_request_target runs with base repository secrets. Checking out PR code provides access. Attackers submit PRs with malicious workflow code. Combined with secrets, enables repository compromise.

Not Understanding pull_request_target Security Context

Developers using pull_request_target without security awareness. Believing same as pull_request. pull_request_target runs in base repo context with write permissions. Has access to secrets. Intended for commenting on PRs, not running untrusted code.

Running Untrusted Code with Repository Secrets

Workflow runs PR code with secrets: steps using npm install, pip install, or running test scripts. PR dependencies may be malicious. Test code from PR executes with secrets. Exfiltration through dependency installation or test execution.

Using actions/checkout Without Explicit ref

Checkout without ref specification: actions/checkout@v3 defaults to triggering ref with pull_request_target. Checks out untrusted PR code. Should use ref: ${{ github.base_ref }} for base code. Missing explicit ref creates vulnerability.

Mixing pull_request_target with Arbitrary Code Execution Steps

Workflows with pull_request_target running: npm run, python scripts, bash commands from repository. PR can modify these scripts. Shell scripts, Python code, npm scripts all under attacker control through PR. Any code execution step vulnerable.

Fixes

1

Use pull_request Instead of pull_request_target for Code Execution

Safe trigger: on: pull_request for workflows running untrusted code. pull_request runs in fork context without secrets. No write permissions. Safe for testing PR code. Use pull_request_target only for commenting or labeling, never code execution.

2

If pull_request_target Required, Checkout Base Repository Code Only

Checkout base branch: - uses: actions/checkout@v3 with: ref: ${{ github.base_ref }}. Checks out trusted base repository code, not PR. PR changes not executed. Safe for workflows needing secrets but not PR code.

3

Use Separate Workflow for Commenting with Artifacts

Split workflows: pull_request workflow generates artifacts. pull_request_target workflow downloads artifacts, posts comments. Artifacts contain test results, not code. pull_request_target never executes PR code. Secure pattern for PR feedback.

4

Implement Approval Required for pull_request_target Workflows

Require approval for external contributors: configure repository settings requiring approval for workflow runs from first-time contributors. Manual review before execution. Prevents automatic exploitation. GitHub environment protection rules.

5

Never Install Dependencies from Untrusted PRs with Secrets

Avoid npm install, pip install in pull_request_target. Dependencies from PR can be malicious. package.json or requirements.txt under attacker control. Use pull_request for dependency installation. Isolate secret access from dependency resolution.

6

Use GitHub Environments with Required Reviewers

Environment protection: jobs requiring secrets use environment with required reviewers. environment: production with protection rules. Manual approval before secret access. Prevents automatic secret exfiltration. GitHub environment settings for sensitive workflows.

Detect This Vulnerability in Your Code

Sourcery automatically identifies remote code execution (rce) via pr code checkout in github actions and many other security issues in your codebase.