fix: route untrusted workflow inputs through env to prevent shell injection - #149
Merged
Merged
Conversation
…ection
Generated workflows interpolated workflow_dispatch inputs and
pull_request event fields directly into run: shell bodies. GitHub
substitutes ${{ ... }} into the script text before the shell parses it,
so a value containing a single quote, backtick, or $(...) breaks out of
its argument and executes as shell. This is both a correctness bug for
legitimate values carrying shell metacharacters and an injection vector
in the external-update receiver.
Bind each untrusted value to a step-level env: variable and reference it
as a quoted shell variable, matching the pattern the hotfix workflow
already uses.
Sites converted:
- external.go: source_repo, deploy_name, environment, sha, version, artifacts
- promote.go: mode input echoed in the validate step
- pr_preview.go: pull_request base/head SHAs in detect-changes and plan steps
Signed-off-by: Joshua Temple <joshua.temple@stablekernel.com>
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.
Problem
Generated workflows interpolated untrusted GitHub Actions context directly into
run:shell bodies. GitHub substitutes${{ ... }}into the script text before the shell parses it, so a value containing a single quote, backtick, or$(...)breaks out of its argument. This is a correctness bug for legitimate values carrying shell metacharacters and, in the external-update receiver, an injection vector that lets a dispatch escalate from writing state to running arbitrary shell with that job's secrets.Fix
Bind each untrusted value to a step-level
env:variable and reference it as a quoted shell variable ("$VAR"), the pattern the hotfix workflow already uses.Sites converted:
internal/generate/external.go- source_repo, deploy_name, environment, sha, version, artifactsinternal/generate/promote.go- mode input echoed in the validate stepinternal/generate/pr_preview.go- pull_request base/head SHAs in the detect-changes and plan steps (attacker-influenceable on fork PRs)Untrusted here means
inputs.*,github.event.*, andgithub.event.inputs.*. Trusted contexts cascade controls (github.sha, github.ref, github.run_id, secrets.*, static literals) are left unchanged. Other generators (orchestrate, release, the hotfix path, the github-script-based notify-primary step) already route untrusted values throughenv:/with:/JS and were verified, not changed.Verification
run:bodies contain no${{ inputs. }}or${{ github.event. }}interpolation and that values flow throughenv:and are consumed as quoted shell variables.artifactspayload containing a single quote,$(...), and a backtick, and asserts the recorded artifact value round-trips byte-for-byte through the receiver. Passes locally under act + gitea.go build ./... && go test ./...green; e2e module builds and vets clean;golangci-lint run ./...clean on both modules.