chore(ci): harden GitHub Actions workflows with zizmor - #2740
Merged
FonduemangVI merged 5 commits intoJun 21, 2026
Conversation
Contributor
Reviewer's GuideIntroduces zizmor as a pre-commit hook and updates multiple GitHub Actions workflows to harden security by tightening permissions, disabling unnecessary credential persistence, reducing template interpolation in shell, and simplifying Python dependency caching. Flow diagram for deploy-pr workflow permissions and jobsflowchart LR
Trigger["Workflow Trigger<br>workflow_run: Trigger PR Build"]
subgraph Workflow_deploy_pr[Workflow deploy-pr]
direction TB
BuildJob["Job build<br>permissions:<br>- contents: read<br>- actions: read"]
CommentJob["Job comment-pr<br>permissions:<br>- contents: read<br>- pull-requests: write"]
end
Trigger --> BuildJob
BuildJob -->|needs: build<br>outputs url, branch_url, pr_sha, pr_number| CommentJob
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
Contributor
Author
|
flagging @saltydk since you've done some security hardening in the past here. |
Contributor
|
Deploying with ⚡ Cloudflare Pages
|
Contributor
There was a problem hiding this comment.
Hey - I've left some high level feedback:
- In the
deploy-pr.ymlcomment step you’ve moved most template expressions intoenv, butsecrets.GITHUB_TOKENis still interpolated directly inside therun:block; consider passing it viaenv:as well to keep all sensitive values out of the shell command line and align with the rest of the hardening changes. - For workflows where you’ve added
cache: piptoactions/setup-python, it may be worth explicitly settingcache-dependency-path(for example todocs/requirements.txt) so the cache key tracks the actual dependency file you use rather than relying on the default.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In the `deploy-pr.yml` comment step you’ve moved most template expressions into `env`, but `secrets.GITHUB_TOKEN` is still interpolated directly inside the `run:` block; consider passing it via `env:` as well to keep all sensitive values out of the shell command line and align with the rest of the hardening changes.
- For workflows where you’ve added `cache: pip` to `actions/setup-python`, it may be worth explicitly setting `cache-dependency-path` (for example to `docs/requirements.txt`) so the cache key tracks the actual dependency file you use rather than relying on the default.Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Contributor
|
Deploying with ⚡ Cloudflare Pages
|
rcdailey
force-pushed
the
chore/zizmor-hardening
branch
from
May 21, 2026 14:27
b08bda8 to
07234d1
Compare
Contributor
|
Deploying with ⚡ Cloudflare Pages
|
Contributor
|
Deploying with ⚡ Cloudflare Pages
|
rcdailey
force-pushed
the
chore/zizmor-hardening
branch
from
June 7, 2026 13:11
24b2ff2 to
06d9741
Compare
Contributor
|
Deploying with ⚡ Cloudflare Pages
|
rcdailey
force-pushed
the
chore/zizmor-hardening
branch
from
June 10, 2026 22:51
06d9741 to
4ea8185
Compare
Contributor
|
Deploying with ⚡ Cloudflare Pages
|
Apply security hardening across all workflow files based on zizmor static analysis findings. Workflow-level permissions are locked down to least privilege, and a zizmor pre-commit hook enforces ongoing compliance. - Add permissions: contents: read at workflow level to all workflows missing explicit permissions - Add persist-credentials: false to all actions/checkout steps to prevent credential leakage - Narrow deploy-pr.yml job-level permissions; remove overly broad workflow-level block - Move inline expression interpolations to env vars in deploy-pr.yml comment step to prevent injection - Consolidate pip caching in deploy.yml and deploy-pr.yml to use setup- python built-in cache - Add zizmor: ignore annotations for intentional artipacked and cache- poisoning suppressions - Add zizmor pre-commit hook (v1.25.0) for continuous static analysis
- Move secrets.GITHUB_TOKEN to job-level env block in deploy-pr comment step - Replace inline secret interpolation with env var reference in curl command - Add cache-dependency-path: docs/requirements.txt to setup-python in both workflows
Addresses remaining zizmor findings by moving user-controllable template
expressions out of run steps and into env blocks, and quoting unquoted
shell variable references.
- Move PAT secret to env block and use ${PAT} in git push URL in
automatic-changelog.yml
- Replace ${{ github.workspace }} with $GITHUB_WORKSPACE and quote
variable references in deploy-pr.yml
- Remove unnecessary checkout step from comment-pr job that had no files
to check out
- Move github.event.before and github.sha to env block in
mkdocs_bug_prevent.yml
- Quote $GITHUB_ENV redirect target and shell variables consistently
rcdailey
force-pushed
the
chore/zizmor-hardening
branch
from
June 21, 2026 12:49
4ea8185 to
98acc83
Compare
FonduemangVI
approved these changes
Jun 21, 2026
FonduemangVI
left a comment
Contributor
There was a problem hiding this comment.
Good to go. Thanks for this
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.
Pull Request
Purpose
This PR adds zizmor as a pre-commit hook and addresses the security findings it reports against the GitHub Actions workflows in this repo.
zizmor is a static analysis tool for GitHub Actions workflows. It catches common security misconfigurations (credential leaks, template injection, overly broad permissions, etc.) before they ship. Adding it to pre-commit means future workflow changes get checked automatically.
Approach
Fixes applied:
persist-credentials: falseto checkout steps that don't need git push access. This prevents the GitHub token from being persisted in the local git config, reducing the attack surface if an action later accesses the.gitdirectory.permissions:blocks to workflows that previously relied on the default (broad) token permissions. Each job now requests only what it actually needs.deploy-pr.ymlpermissions from workflow-level to job-level so the build job (read-only) doesn't inherit write permissions meant for the comment job.actions/cache+ pip cache directory steps withsetup-python's built-incache: pipin the deploy workflows. Same caching behavior, less boilerplate.${{ ... }}) inrun:blocks to environment variables where possible. This prevents potential code injection if an interpolated value ever contains shell metacharacters. Specifically:deploy-pr.ymlcomment step now usesenv:block instead of inline interpolationautomatic-changelog.ymluses${LAST_EDIT_TIME}(shell expansion) instead of${{ env.LAST_EDIT_TIME }}(template expansion)Intentional suppressions (with inline justification comments):
artipackedon the two checkouts that usesecrets.PAT: these workflows need credentials persisted to push commits back to the repo.dangerous-triggersondeploy-pr.yml: theworkflow_runtrigger is the standard secure pattern for accessing secrets in PR preview deployments.cache-poisoningon the deploy workflows: only trusted pushes to master (or repo-owned workflow_run triggers) can write to the cache; fork PRs cannot poison it.Pre-commit hook:
Added zizmor v1.25.0 via the zizmorcore/zizmor-pre-commit repo. It runs on
.github/workflows/*.ymlfiles.Open Questions and Pre-Merge TODOs
cache: piponsetup-python(this is functionally equivalent to the old manual approach, just less code)Requirements
Summary by Sourcery
Harden GitHub Actions workflows by tightening permissions, reducing credential exposure, and integrating automated security scanning for workflow configs.
New Features:
Enhancements:
CI:
Deployment: