FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

ci: pass release inputs through env in the release workflow by WAHIB-EL-KHADIRI · Pull Request #3252 · polybar/polybar · GitHub

ci: pass release inputs through env in the release workflow - #3252

Open
WAHIB-EL-KHADIRI wants to merge 1 commit into
polybar:masterfrom
WAHIB-EL-KHADIRI:ci/harden-release-workflow
Open

ci: pass release inputs through env in the release workflow#3252
WAHIB-EL-KHADIRI wants to merge 1 commit into
polybar:masterfrom
WAHIB-EL-KHADIRI:ci/harden-release-workflow

Conversation

WAHIB-EL-KHADIRI commented Aug 25, 2026
edited
Loading

Copy link
Copy Markdown

What

.github/workflows/release.yml expands the workflow_dispatch tag input straight into a shell:

run: |
  if [ ${{  github.event_name }} == 'workflow_dispatch' ]; then
    RELEASE_TAG=${{ github.event.inputs.tag }}

${{ ... }} is substituted as text before bash parses the line, and the assignment is unquoted, so a tag input containing shell metacharacters is executed rather than assigned.

That value then flows onward: it is written to GITHUB_ENV as RELEASE_TAG, POLYBAR_DIR and POLYBAR_ARCHIVE, and those are interpolated into the two actions/github-script bodies, which are JavaScript source:

const tag = '${{ env.RELEASE_TAG }}';
const fname = '${{ env.POLYBAR_ARCHIVE }}'
release_id: '${{ env.RELEASE_ID}}',

A single quote in any of them closes the string literal and the rest is evaluated as code, in steps holding GITHUB_TOKEN.

On severity: workflow_dispatch requires write access, so this is defense in depth, not an externally reachable vulnerability. I am raising it because the file already does the right thing one step further down — RELEASE_BODY is passed via env and read with process.env, with a comment explaining why — so this is mostly a consistency gap rather than a design disagreement.

The fix

Route every one of these through env: and read them with process.env, matching the existing RELEASE_BODY handling. Behaviour is unchanged.

Also adds permissions: contents: write to the job — the token needs to update releases and nothing more.

One thing worth flagging

The Get Version step carried:

if: ${{ github.event.inputs.tag }} != ''

Because this mixes an expression with trailing text, the result is a string — " != ''" on a release trigger — and any non-empty string is truthy, so the step always ran. That happens to be correct, since the else branch is what handles the release: published path.

Worth being explicit about the trap: "fixing" this to if: github.event.inputs.tag != '' would break automatic releases, because the step would then be skipped on the release trigger and RELEASE_TAG would never be set. The only correct fix is to drop the condition, which is what this PR does.

Verification

The workflow parses cleanly and no ${{ }} expansion remains inside any run: or script: body — every value now reaches them through env.

AI assistance

I used an AI coding agent to sweep release workflows for this pattern and to draft this description. What I confirmed in the file myself, rather than accepted from a model: that RELEASE_BODY further down the same job already goes through env: and is read with process.env, with a comment explaining why — so this is a gap in an approach the file had already chosen, not one I am importing — and that workflow_dispatch is the only path to the input, which is the basis for the severity note above.

The workflow_dispatch tag input was expanded unquoted into the shell of
the Get Version step, and the values derived from it were interpolated
into the two github-script bodies as JavaScript source. Routing them
through env keeps them data.

Drops the Get Version condition, which was malformed: the mixed
expression always evaluated to a non-empty string, so the step ran
unconditionally. That is the behaviour the workflow needs, since the
else branch handles the release trigger.

Adds the least-privilege permissions block the file had never declared.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

Copy link
Copy Markdown
Author

Heads up on something mechanical: the CI workflow here is at action_required and has never executed on this branch, so this PR has had no check results since it was opened. The branch is even with main.

If a maintainer approves the run, it can at least be assessed on a real CI outcome.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant


Back | FazBrowse Home | New Git URL