Conversation
Assisted-by: Claude (Anthropic)
zizmor flagged direct ${{ inputs.* }} interpolation inside run: blocks in
the parse, setup-globus, and upload composite actions as code-injection
risk. Route inputs through env vars instead so shell expansion cannot be
influenced by template expansion.
Assisted-by: Claude (Anthropic)
- Set persist-credentials: false on every actions/checkout step; none of these jobs need the git token to persist past the job. - Add an explicit contents: read workflow-level permissions block to docs.yml so the build job no longer runs with default (broad) permissions; the deploy job keeps its own narrower explicit grant. Assisted-by: Claude (Anthropic)
- Add zizmor as a pre-commit hook (pedantic persona) so CI-security findings surface locally, matching the check now run in CI. - Add a 7-day cooldown to the github-actions dependabot updates group, switch it to monthly to match the pre-commit bot's cadence, and rename the group key from the deprecated actions alias to github-actions. - Set autoupdate_schedule: monthly on the existing pre-commit ci: block. - Add .github/zizmor.yml with a documented ignore for the dangerous-triggers finding on semantic-pr-check.yml's pull_request_target trigger (no checkout step, PR-title-only, needed for a write-scoped token on fork PRs). Assisted-by: Claude (Anthropic)
prek auto-update --freeze --cooldown-days 7 found no releases outside the cooldown window, so every hook stays on its current version, now pinned by SHA. Also tune the new zizmor hook to --min-severity=low so it doesn't fail on the pedantic persona's informational-only job-naming findings. Assisted-by: Claude (Anthropic)
The rucio job already guarded against running on arc-runner-set-uchicago for pull_request events from forks, but every other job on that self-hosted runner (test-actions in ci.yml, and all uchicago.yml jobs besides rucio) had no such guard. Any fork could open a PR and have its branch's shell scripts execute directly on the lab's self-hosted infrastructure. Apply the same fork check consistently to close the gap. Assisted-by: Claude (Anthropic)
Regression:
|
Moving the parse composite action's inputs to env vars (to fix
zizmor's template-injection findings) stopped the ${NODE_NAME} host
value from being re-expanded as shell syntax: HOST's value became the
inert literal string "${NODE_NAME}" instead of the runner's real
hostname. Export the runner's NODE_NAME into GITHUB_ENV after checkout
in each job and pass it as host: env.NODE_NAME (the GHA expression),
matching the pattern already documented in docs/workflows/benchmarks.md
and development.md.
Reported-by: qibinlei
Assisted-by: Claude (Anthropic)
|
Thanks for catching this, @qibinlei — confirmed and fixed in 8539980. Added an "Export node name" step ( |
Summary
CI-security hardening pass: pin all GitHub Actions to SHAs, fix zizmor findings, add zizmor as a pre-commit hook, add a dependabot cooldown, and close a gap where fork PRs could run arbitrary code on the self-hosted runner.
Changes
npx actions-up), each with a# vX.Y.Zcomment. Verified every pin against the upstream tag ref.template-injectionfindings: theparse,setup-globus, anduploadcomposite actions interpolated${{ inputs.* }}directly intorun:shell blocks. Routed all of them throughenv:instead.artipackedfindings: addedpersist-credentials: falseto everyactions/checkoutstep (none of these jobs need to push using the checkout token).excessive-permissionsfinding: added a workflow-levelpermissions: contents: readtodocs.ymlso thebuildjob no longer runs with default permissions (thedeployjob already had its own narrower explicit grant).--persona=pedanticas a pre-commit hook, scoped with--min-severity=lowso it doesn't fail on the persona's informational-only job-naming nits (see "zizmor ignores" below for the one real ignore).github-actionsgroup, switched it to monthly, and renamed the group key from the deprecatedactionsalias togithub-actions..pre-commit-config.yaml: froze every hook to its current tag's SHA (prek auto-update --freeze --cooldown-days 7); no hook had a release outside the cooldown window, so no versions moved. Also setautoupdate_schedule: monthlyon the existingci:block.ruciojob inuchicago.ymlalready skipped itself forpull_requestevents from forks, but every other job onarc-runner-set-uchicago(includingtest-actionsinci.yml) had no such guard — any fork could open a PR and have its branch's shell scripts execute directly on the lab's self-hosted infrastructure. Applied the samegithub.event.pull_request.head.repo.fork == falseguard everywhere that job pattern is used.Major version changes
None.
actions-upmoved every action reference to a SHA of the same tag it was already on (e.g.actions/checkout@v7→v7.0.1pinned by SHA); no major bumps were available/applicable.prek auto-updatelikewise found no hook releases outside the 7-day cooldown, so no pre-commit hook moved versions either.One version note (not major, but worth flagging):
prefix-dev/setup-pixiin.github/actions/parse/action.ymlwas onv0.9.3whileci.yml/docs.ymlalready usedv0.10.1;actions-upbrought it in line with the other two call sites atv0.10.1(SHA-pinned).Held back
pixi.toml:exclude-newercooldown — the skill's default step 6 asks for a 7-dayexclude-newercooldown on pixi-managed dependencies.exclude-newerwas only added to pixi in v0.67.0, but this repo pinspixi-version: v0.49.0in three places (ci.yml,docs.yml,.github/actions/parse/action.yml). Adding the setting now would very likely break everypixi run/pixi installinvocation in CI against an old pixi that doesn't recognize the field. Skipped; bumping pixi itself to ≥0.67.0 is a separate, non-security change that deserves its own PR and testing.zizmor ignores
dangerous-triggersonsemantic-pr-check.yml(pull_request_target): this workflow never checks out the PR's code — there's noactions/checkoutstep at all — and only reads the PR title via the GitHub API throughamannn/action-semantic-pull-request.pull_request_targetis used deliberately so PRs from forks still get astatuses: write-capable token to report the check; a plainpull_requesttrigger is forced read-only for fork PRs and would silently fail to post the status, defeating the point of validating first-time contributors' PR titles. Documented in.github/zizmor.yml.Verification
uvx zizmor --persona=pedantic --min-severity=low .github→ clean (0 low/medium/high findings; the informational job-naming findings are filtered by design and are not security-relevant).uvx prek run --all-files→ all hooks pass, including the newly addedzizmorhook.git ls-remotefor its upstream tag ref before committing.