Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion .github/actions/setup-llvm22/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,17 @@ runs:
- name: LLVM 22 (Windows, official MSVC tarball)
if: runner.os == 'Windows'
shell: pwsh
# `inputs.version` arrives through the environment, NOT through `${{ }}`
# interpolated into the script body. A template expansion is substituted
# as raw text before pwsh ever parses the line, so an input containing a
# quote plus a statement separator executes as code with the runner's
# privileges; reading `$env:` is a plain string load with no such step.
# Caught by zizmor's `template-injection` audit at High confidence.
env:
LLVM_VERSION: ${{ inputs.version }}
run: |
$ErrorActionPreference = "Stop"
$ver = "${{ inputs.version }}"
$ver = $env:LLVM_VERSION
$url = "https://github.com/llvm/llvm-project/releases/download/llvmorg-$ver/clang+llvm-$ver-x86_64-pc-windows-msvc.tar.xz"
Write-Host "downloading $url"
curl.exe -sSL --retry 3 -o "$env:RUNNER_TEMP\llvm.tar.xz" $url
Expand Down
31 changes: 31 additions & 0 deletions .github/zizmor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,34 @@ rules:
# change that needs its own carefully-tested PR (a mistake only
# manifests at the next tag). Tracked as follow-up.
- release-packages.yml

# 2026-08-05: three findings, all audit-confidence Low, all of them the one
# `LLVM_SYS_221_PREFIX=<prefix>` line that setup-llvm22 exists to write —
# once per platform arm. This gate went red at #7353, the commit that
# introduced that action, and stayed red for ~40 main commits.
#
# This is a scoped carve-out and NOT the fix. Measured: the audit is
# satisfied only by not writing the environment file at all. A dynamic value
# into $GITHUB_ENV always reports (a static literal does not; ours is
# `brew --prefix` / `llvm-config --prefix` output), and the pwsh arm reports
# even for a literal, because zizmor cannot evaluate `Out-File`. The only
# clean form is `$GITHUB_OUTPUT` + composite-action outputs — which is a real
# improvement in the abstract and a bad trade here: measured across
# .github/workflows, that is 44 jobs needing an `id:` and 140 downstream
# steps each needing `env: LLVM_SYS_221_PREFIX: ${{ steps.<id>.outputs.prefix }}`,
# because llvm-sys reads the prefix from the environment at build time. That
# re-creates precisely the "44 inline recipes" this action was written to
# delete, across 18 files, none of it verifiable outside CI.
#
# The exposure being traded away is small and bounded: the written values are
# filesystem paths produced by locally installed toolchains, on a composite
# action whose callers all run under `pull_request` / `push`, never
# `pull_request_target` or `workflow_run`. zizmor's own confidence is Low for
# this reason.
#
# Ratchet: delete this entry when setup-llvm22 moves to outputs. `action.yml`
# is unambiguous only because it is the repo's ONLY composite action — adding
# a second one silently widens this, so re-scope it at that point.
github-env:
ignore:
- action.yml
41 changes: 41 additions & 0 deletions changelog.d/TMP.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
Fixed the `zizmor` GitHub Actions security gate, which had been failing on every
`main` commit since #7353.

`#7353` created `.github/actions/setup-llvm22/action.yml` and, with it, four
high-severity findings. The gate went red on that commit and stayed red for
roughly 40 consecutive `main` commits. `#7388` (clang-22 in setup-llvm22) and
`#7393` (a `concurrency` group for gc-native-roots) are both innocent — they
only shifted the reported line numbers, which is what made them look
implicated.

One finding is properly fixed. The Windows arm interpolated a composite-action
input straight into a PowerShell script body (`$ver = "${{ inputs.version }}"`),
which `template-injection` flags at **High** confidence: a template expansion is
substituted as raw text before pwsh parses the line, so an input carrying a
quote plus a statement separator would execute as code with the runner's
privileges. The input now arrives through an `env:` block and is read as
`$env:LLVM_VERSION`, which is a plain string load with no such step.

Three findings are suppressed, with reasoning, in `.github/zizmor.yml`. All
three are `github-env` at **Low** confidence, and all three are the single
`LLVM_SYS_221_PREFIX=<prefix>` line the action exists to write, once per
platform arm. The audit was measured to be satisfiable only by not writing the
environment file at all — a dynamic value into `$GITHUB_ENV` always reports (a
static literal does not), and the pwsh arm reports even for a literal because
zizmor cannot evaluate `Out-File`. The clean alternative is `$GITHUB_OUTPUT`
plus composite-action outputs, and it was measured across `.github/workflows`
at **44 jobs** needing an `id:` and **140 downstream steps** each needing
`env: LLVM_SYS_221_PREFIX: ${{ steps.<id>.outputs.prefix }}`, because llvm-sys
reads the prefix from the environment at build time. That recreates precisely
the "44 inline recipes" duplication the action was written to remove, across 18
files, none of it verifiable outside CI — so it was rejected as a bad trade for
a Low-confidence finding on filesystem paths produced by locally installed
toolchains, in an action whose callers only ever run under `pull_request` and
`push`. The carve-out is a dated ratchet with an explicit delete-condition, in
the same style as the file's existing entries.

Verified with the repo's SRI-pinned zizmor 1.28.0: with the pristine config and
the template-injection fix the audit reports 3 high findings and exits 14; with
the carve-out it exits 0, and the `ignored` count rises from 119 to 122 — three,
matching the three suppressed findings exactly, so the entry is not
over-broad.
Loading