Skip to content

Fix: Env-mediate expressions in run blocks - #147

Merged
tykeal merged 1 commit into
lfreleng-actions:mainfrom
modeseven-lfreleng-actions:fix/zizmor-template-injection
Jul 29, 2026
Merged

Fix: Env-mediate expressions in run blocks#147
tykeal merged 1 commit into
lfreleng-actions:mainfrom
modeseven-lfreleng-actions:fix/zizmor-template-injection

Conversation

@ModeSevenIndustrialSolutions

Copy link
Copy Markdown
Contributor

Why

zizmor's template-injection audit reports GitHub expressions that expand directly inside run: blocks. The expansion happens before the shell sees the script, so a value carrying shell syntax becomes code rather than data.

Each expression now reaches the shell through the step environment instead. These findings predate the change to the organisation zizmor floor (lowinformational); they were simply below the old threshold.

Please review the diff carefully

The transformation is not purely mechanical. Swapping ${{ expr }} for ${VAR} changes the quoting rules, because the original was substituted by GitHub before the shell ran and the replacement is an ordinary shell variable. Three contexts silently stop working:

Context Before After
var='${{ expr }}' substituted by GitHub literal string
echo 'text ${{ expr }}' substituted by GitHub literal string
cat <<'EOF'${{ expr }} substituted by GitHub literal string

shellcheck catches the first two. It does not catch the heredoc case. That one was found in url-validity-action, where 27 references would have rendered the job summary as variable names instead of results.

What was verified before raising this

  • zizmor --persona auditor --min-severity informational — no findings
  • actionlint (including shellcheck) — clean
  • yamllint — clean
  • A purpose-built audit for generated variables landing in single quotes or quoted heredocs — clean. It was validated by confirming it detects 33 such problems in the unrepaired output for url-validity-action.
  • Diff restricted to workflow and action definitions; no dependabot.yml or version-pin comment changes rode along

Note on the generated names

Where zizmor's names push a line past the length limit, the line carries a yamllint disable-line directive. Shortening them was rejected: the short forms are unique only within one env: block, so a global rewrite merges distinct variables and leaves dangling references — verified by observing exactly that failure.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR mitigates zizmor template-injection findings by removing direct ${{ ... }} GitHub expression expansions from run: blocks and instead passing those values into the shell via step env: variables, so the shell only sees data (shell variables) rather than pre-expanded script content.

Changes:

  • Added step-level env: entries that map step outputs to environment variables (with targeted yamllint line-length suppressions where needed).
  • Updated bash validation logic to reference the new environment variables instead of ${{ steps.*.outputs.* }} inside run: scripts.
  • Applied the same pattern to cache-key validation and artifact-path verification steps.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

zizmor's template-injection audit reports GitHub expressions that
expand directly inside run blocks. The expansion happens before the
shell sees the script, so a value carrying shell syntax becomes code
rather than data.

Routes each expression through the step environment instead. The
value reaches the shell as a variable, and the expansion leaves the
script body entirely.

The generated names push some lines past the line-length limit, so
those lines carry a yamllint directive. Shortening the names was
rejected: they are unique only within one env block, so a global
rewrite merges distinct variables and leaves dangling references.

Lowering the organisation zizmor floor to informational surfaced
these; they predate the change and sat below the old threshold.

Co-authored-by: Claude <claude@anthropic.com>
Signed-off-by: Matthew Watkins <mwatkins@linuxfoundation.org>
Copilot AI review requested due to automatic review settings July 29, 2026 10:09

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated no new comments.

@tykeal tykeal left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Dependamerge
Approved this pull request ✅

@tykeal
tykeal merged commit 814a1a6 into lfreleng-actions:main Jul 29, 2026
15 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants