Skip to content

Script injection: github.ref_name / github.ref interpolated into shell run: on push path #26

Description

@jiridanek

Summary

action.yml interpolates ${{ github.ref_name }} and ${{ github.ref }} directly into the composite action's run: (shell) block on the non-PR (push / workflow_dispatch) path:

COMMIT_OID="${{ github.sha }}"
REF="${{ github.ref }}"
PR_NUMBER=$(gh pr list \
  --repo "$GITHUB_REPOSITORY" \
  --head "${{ github.ref_name }}" \
  --state open --json number --jq '.[0].number // empty' 2>/dev/null || true)

Because these branch-derived values are interpolated into a shell context, a branch named e.g. foo-$(command) — or one using backticks or a " to break out of the double quotes — results in command execution when a consuming workflow runs on push or workflow_dispatch for that ref.

Impact

Reachable by anyone who can push a branch (or workflow_dispatch) to a repo that uses this action — i.e. it requires write access, so the marginal privilege is limited (such a user can generally already run code in CI). Even so, it's a script-injection footgun in a first-party action: it defeats the usual expectation that uses: of a trusted action is safe, and the injected code runs with whatever token the caller grants (commonly code-quality: write).

Suggested fix

Pass the untrusted values via env: and reference them as quoted shell variables, per GitHub's own hardening guidance (https://docs.github.com/en/actions/security-for-github-actions/security-guidelines/security-hardening-for-github-actions#understanding-the-risk-of-script-injections):

env:
  GH_REF: ${{ github.ref }}
  GH_REF_NAME: ${{ github.ref_name }}
run: |
  REF="$GH_REF"
  PR_NUMBER=$(gh pr list --repo "$GITHUB_REPOSITORY" --head "$GH_REF_NAME" \
    --state open --json number --jq '.[0].number // empty' 2>/dev/null || true)

Version

Observed on v1.4.1 (commit 1c15be3).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions