Skip to content

fix: pass version inputs via env to prevent expression injection - #225

Merged
davidkarlsen merged 1 commit into
helm:mainfrom
cpanato:harden-action-yml-injection
Sep 19, 2026
Merged

davidkarlsen merged 1 commit into
helm:mainfrom
cpanato:harden-action-yml-injection

Conversation

@cpanato

@cpanato cpanato commented Sep 17, 2026

Copy link
Copy Markdown
Member

The composite run: step spliced ${{ inputs.version }}, ${{ inputs.yamllint_version }} and ${{ inputs.yamale_version }} directly into a bash command line. GitHub substitutes ${{ }} textually before bash parses the script, so a caller that derives any of those values from untrusted data (a PR title, branch name or issue body) can inject arbitrary shell commands into this action.

Pass each input through step-level env: instead and reference the quoted shell variables, so the value stays a single argv element that bash never re-evaluates. Also quote $GITHUB_ACTION_PATH so the cd does not word-split on a path containing spaces.

The env vars are deliberately not named CT_*, since chart-testing reads CT_* from the environment as its own viper configuration.

ct.sh needed no change: it already quotes "${2#v}" and stores argument values verbatim without re-evaluating them.

Verified: reproduced command execution against the old form (--version '3.14.0; touch /tmp/PWNED' created the marker file) and confirmed the env: form passes the same hostile value through inert. actionlint clean.

The composite `run:` step spliced `${{ inputs.version }}`,
`${{ inputs.yamllint_version }}` and `${{ inputs.yamale_version }}`
directly into a bash command line. GitHub substitutes `${{ }}`
textually before bash parses the script, so a caller that derives any of
those values from untrusted data (a PR title, branch name or issue body)
can inject arbitrary shell commands into this action.

Pass each input through step-level `env:` instead and reference the
quoted shell variables, so the value stays a single argv element that
bash never re-evaluates. Also quote `$GITHUB_ACTION_PATH` so the `cd`
does not word-split on a path containing spaces.

The env vars are deliberately not named `CT_*`, since chart-testing
reads `CT_*` from the environment as its own viper configuration.

`ct.sh` needed no change: it already quotes `"${2#v}"` and stores
argument values verbatim without re-evaluating them.

Verified: reproduced command execution against the old form
(`--version '3.14.0; touch /tmp/PWNED'` created the marker file) and
confirmed the `env:` form passes the same hostile value through inert.
actionlint clean.

Signed-off-by: Carlos Panato <ctadeu@gmail.com>
@cpanato
cpanato force-pushed the harden-action-yml-injection branch from 854739e to 46209b7 Compare September 17, 2026 08:29
@davidkarlsen
davidkarlsen merged commit 6baaad1 into helm:main Sep 19, 2026
4 checks passed
@cpanato
cpanato deleted the harden-action-yml-injection branch September 21, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants