Skip to content

fix: remove GitHub Actions script injection in debug_info step (CWE-94) - #229

Merged
piontec merged 1 commit into
mainfrom
fix-shell-injction
Jun 24, 2026
Merged

fix: remove GitHub Actions script injection in debug_info step (CWE-94)#229
piontec merged 1 commit into
mainfrom
fix-shell-injction

Conversation

@piontec

@piontec piontec commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

What

Fixes a GitHub Actions script injection (CWE-94) in the debug_info "Print github context JSON" step of four reusable workflows, and adds a report-only zizmor self-scan as a regression guardrail.

Reported in giantswarm/giantswarm#36940 (severity 8.8 High, confirmed with a working PoC).

The vulnerability

The step interpolated ${{ toJson(github) }} directly into a run: shell heredoc:

- name: Print github context JSON
  run: |
    cat <<EOF
    ${{ toJson(github) }}
    EOF

GitHub Actions performs literal text substitution of ${{ }} into the script before the shell runs it. toJson(github) embeds attacker-controllable fields (commit messages, PR titles/bodies, author name/email). A crafted commit message containing an EOF line followed by shell commands breaks out of the heredoc and runs arbitrary commands on the runner. Realistic vector: a maintainer squash-merging an external PR without editing the auto-populated commit message.

The fix

Pass the context through an env: variable so the shell treats it as data, not script text — the same safe pattern already used for COMMIT_MESSAGE in create-release.yaml:

- name: Print github context JSON
  env:
    GITHUB_CONTEXT: ${{ toJson(github) }}
  run: echo "$GITHUB_CONTEXT"

Applied identically to:

  • create-release.yaml
  • create-release-pr.yaml
  • update-chart.yaml
  • ensure-major-version-tags.yaml

Guardrail (report-only)

CodeQL was enabled on this repo but did not catch this. This PR adds a non-blocking zizmor self-scan job to validate-workflows.yaml (continue-on-error: true) that uploads findings to the Security tab. It does not gate PRs on the repo's pre-existing findings; it exists to surface regressions of this class.

Verification

  • zizmor before → after: High template-injection findings dropped 31 → 27 — exactly the four toJson(github) sinks are gone.
  • No cat <<EOF heredocs remain in any workflow; all toJson(github) now sit under env:.
  • The new zizmor job's checkout uses persist-credentials: false, so it introduces no new findings.
  • All edited workflow files parse as valid YAML.

Out of scope (follow-up)

zizmor surfaced ~180 pre-existing findings: other High template-injection sites (branch names / inputs / github.actor in run: blocks), 21 artipacked checkouts missing persist-credentials: false, 7 github-app, 1 unpinned-uses. These are lower-severity than the merged-commit-message vector and touch working release machinery — to be addressed as a separate hardening effort. The report-only scan keeps them visible in the Security tab.

🤖 Generated with Claude Code

The `debug_info` "Print github context JSON" step interpolated
`${{ toJson(github) }}` directly into a `run:` shell heredoc in four
reusable workflows. GitHub Actions substitutes `${{ }}` into the script
before the shell runs, so attacker-controllable event fields (e.g. a
commit message containing an `EOF` line plus shell commands) could break
out of the heredoc and execute arbitrary commands on the runner.

Pass the context through an `env:` variable and print it with
`echo "$GITHUB_CONTEXT"` so it is treated as data, mirroring the existing
safe `COMMIT_MESSAGE` pattern in create-release.yaml.

Also add a report-only zizmor self-scan to validate-workflows.yaml so this
class of issue is surfaced in the Security tab going forward (CodeQL did
not catch it). It is non-blocking (continue-on-error) and does not gate on
the repo's pre-existing findings.

Reported via giantswarm/giantswarm#36940.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@piontec
piontec requested a review from a team as a code owner June 24, 2026 08:09
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

@piontec
piontec merged commit 676c085 into main Jun 24, 2026
5 checks passed
@piontec
piontec deleted the fix-shell-injction branch June 24, 2026 11:24
Comment on lines +58 to +79
analyze-actions:
name: Analyze workflows with zizmor (report-only)
runs-on: ubuntu-24.04
permissions:
contents: read
security-events: write # upload SARIF to the Security tab (code scanning is enabled)
actions: read
steps:
- name: Checkout code
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
with:
persist-credentials: false

# Report-only: zizmor uploads findings to the Security tab for visibility but never
# blocks PRs. The repo carries pre-existing findings that are tracked separately; this
# scan is here to surface regressions (e.g. re-introducing `${{ toJson(github) }}` in a
# `run:` block) that CodeQL did not catch. See giantswarm/giantswarm#36940.
- name: Run zizmor (non-blocking)
continue-on-error: true
uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7
with:
persona: regular

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.

fyi @giantswarm/team-honeybadger zizmor is already available as a devctl-managed workflow https://github.com/giantswarm/devctl/blob/main/pkg/gen/input/workflows/internal/file/zizmor_base.yml.template

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.

5 participants