Skip to content

Pass github.head_ref through env in hotfix-generate workflow#8601

Open
arpitjain099 wants to merge 1 commit into
Azure:mainfrom
arpitjain099:chore/harden-hotfix-headref
Open

Pass github.head_ref through env in hotfix-generate workflow#8601
arpitjain099 wants to merge 1 commit into
Azure:mainfrom
arpitjain099:chore/harden-hotfix-headref

Conversation

@arpitjain099
Copy link
Copy Markdown

I research software supply chain security and have been going through GitHub Actions workflows for places where untrusted input reaches a shell. Small hardening change to hotfix-generate.yml.

The "Commit changes via API" step puts ${{ github.head_ref }} straight into the gh api command line: once as the ?ref= query parameter and once as the -f branch= value. Because Actions expands ${{ }} into the script text before bash executes it, a branch name with backticks or $(...) would be evaluated as a command. That step runs after the GitHub App token is generated, so it executes with write access.

To be clear about reach: the job's if: requires github.event.pull_request.head.repo.full_name == github.repository, so fork PRs are already excluded. This is therefore defense-in-depth against a push-access account that is malicious or compromised, not an anonymous external vector. I still think it is worth closing because the payload lives in the branch name, which is not something a diff review surfaces.

The change moves the value into a HEAD_REF env var and uses "$HEAD_REF"; environment values are not re-parsed by the shell. Behavior is unchanged for ordinary branch names. The ref: input on the checkout step is an action input rather than a shell expansion, so I left it alone.

…jection

The "Commit changes via API" step interpolates ${{ github.head_ref }}
directly into the gh api command line (the ref query parameter and the
-f branch value). Actions expands ${{ ... }} into the script before bash
runs, so a branch name containing shell metacharacters would be evaluated.
This step runs after a GitHub App token is minted, so the value executes in
a context with write access.

The job is gated to same-repo PRs (head.repo.full_name == github.repository),
which keeps fork PRs out, so this is defense-in-depth against a compromised or
malicious push-access account rather than an anonymous external path. The fix
moves the branch name into a HEAD_REF env var and references "$HEAD_REF", which
the shell does not re-evaluate. No behavior change for normal branch names.

Signed-off-by: Arpit Jain <arpitjain099@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant