fix(ci): prevent command injection via github.head_ref (H26-91) - #256
Merged
Conversation
The "Commit generated pages" step interpolated ${{ github.head_ref }}
directly into a shell run: block. Branch names may contain shell
metacharacters, so a crafted PR head branch achieved arbitrary command
execution on the runner. Bind head_ref to an env var and reference it as
a quoted shell variable so it is treated as data, not code.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
kierantaylorHX
approved these changes
Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
The Commit generated pages step in
.github/workflows/ruby.ymlinterpolated${{ github.head_ref }}directly into a shellrun:block:git push origin HEAD:${{ github.head_ref }} --forcegithub.head_refis the source-branch name of the incoming PR and is attacker-controlled. Git allows branch names containing shell metacharacters, so a PR opened from a crafted branch name executed arbitrary commands on the runner (the job holdspermissions: contents: write). Tracked as H26-91.Fix
Bind the untrusted value to an
env:var and reference it as a quoted shell variable, so it is passed as data rather than parsed as shell source:This is the pattern recommended in GitHub's "Security hardening for GitHub Actions" guidance. Behaviour is unchanged for legitimate branch names.
Validation
The injection was reproduced against this workflow prior to the fix (benign
id/marker payload, authorised test); with this change the branch name is no longer interpreted by the shell.🤖 Generated with Claude Code