fix(ci): GitHub Actions security hardening#159
Open
stevebeattie wants to merge 4 commits into
Open
Conversation
Add .github/zizmor.yml disabling the cosmetic pedantic rules (anonymous-definition, undocumented-permissions, concurrency-limits) and setting the dependabot-cooldown threshold to 3 days. Add the companion cooldown.default-days: 3 to each ecosystem in .github/dependabot.yaml so the threshold is met. Extend the zizmor workflow paths: filter so edits to the config and dependabot files re-run the check. Refs: PSEC-923 Generated-By: claude-guard chain dd432b57ed51d834e2b8f28bb26ba66d Skills-Applied: zizmor-config Skills-Sha: 7dedf1fc9723c0487e7d2b10722852cb5bf2a1835d1e4bb0a462bcc4d3c65a6f Image-Sha: sha256:20335121a95cc1ec4a70b7a8f9327bf74c23563767143377c640546e0a0e2390
The action-lint job publishes the "Action lint" status check, which is a required check on the main branch (per run-facts required_checks with protection_visible=true). A paths: filter that gates a required check lets a PR touching only non-workflow files skip the check and wedge merge. Remove the paths: filter so the workflow runs on all PRs. Refs: PSEC-923 Generated-By: claude-guard chain dd432b57ed51d834e2b8f28bb26ba66d Skills-Applied: actionlint-config Skills-Sha: 7dedf1fc9723c0487e7d2b10722852cb5bf2a1835d1e4bb0a462bcc4d3c65a6f Image-Sha: sha256:20335121a95cc1ec4a70b7a8f9327bf74c23563767143377c640546e0a0e2390
The three repo-check steps interpolate ${{ github.repository_owner }}
and ${{ github.event.repository.name }} directly into run: shell
bodies, so a crafted value could execute as code under the runner.
Move github.event.repository.name into a REPO_NAME env: alias and use
the built-in $GITHUB_REPOSITORY_OWNER for github.repository_owner,
referencing both as double-quoted shell variables.
Refs: PSEC-923
Generated-By: claude-guard chain dd432b57ed51d834e2b8f28bb26ba66d
Skills-Applied: template-injection
Skills-Sha: 7dedf1fc9723c0487e7d2b10722852cb5bf2a1835d1e4bb0a462bcc4d3c65a6f
Image-Sha: sha256:20335121a95cc1ec4a70b7a8f9327bf74c23563767143377c640546e0a0e2390
The actions/checkout step did not set persist-credentials, so the GITHUB_TOKEN credential was left in the local git config. No downstream step performs git writes (the repo checks use the octo-sts token via GH_TOKEN/GITHUB_TOKEN for GitHub API calls, not git), so the safe default persist-credentials: false applies. Refs: PSEC-923 Generated-By: claude-guard chain dd432b57ed51d834e2b8f28bb26ba66d Skills-Applied: artipacked Skills-Sha: 7dedf1fc9723c0487e7d2b10722852cb5bf2a1835d1e4bb0a462bcc4d3c65a6f Image-Sha: sha256:20335121a95cc1ec4a70b7a8f9327bf74c23563767143377c640546e0a0e2390
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Automated GitHub Actions security hardening (zizmor + actionlint + shellcheck,
plus manual review). Four focused, workflow-config-only changes — no
application code is touched.
Changes
Scope down checkout credentials —
persist-credentials: falseon thepresubmit-testing.yamlcheckout. The job passes its token explicitly to thesteps that need it, so leaving the checkout token in
.git/configfor latersteps is unnecessary exposure.
Move template expressions into
env—${{ … }}interpolations inpresubmit-testing.yamlrun:blocks are hoisted into quotedenv:aliases(built-ins use the
$GITHUB_*variables). This removes the shellscript-injection surface created by expanding expressions directly into
inline scripts.
Stop the required "Action lint" check from being un-runnable —
actionlint.yamlgated its triggers on apaths:filter, but its"Action lint" status check is required by branch protection on
main. APR that touches no workflow files would never trigger it, so the required
check would sit permanently pending and block merge. Removing the
paths:filter so the check runs on every PR (fail-closed).
Add a zizmor config + dependabot cooldown — a
.github/zizmor.ymlthatdisables a few cosmetic pedantic rules, and a 3-day cooldown on each
dependabot ecosystem so brand-new (and potentially compromised) dependency
releases aren't pulled the instant they ship.
Note for reviewer
This PR is from a fork. Because patch 0002 makes the "Action lint" check run
on all PRs, it will now run on this PR too (intended). Any OIDC / octo-sts
steps in the privileged workflows that depend on repository-scoped identity may
report as failed or skipped in a fork PR for environmental reasons unrelated to
these changes.
Refs: PSEC-923