Skip to content

Add zizmor to CI and stop double-running the security scan - #6251

Merged
ChrisJBurns merged 3 commits into
mainfrom
harden-actions-workflows-zizmor
Aug 10, 2026
Merged

Add zizmor to CI and stop double-running the security scan#6251
ChrisJBurns merged 3 commits into
mainfrom
harden-actions-workflows-zizmor

Conversation

@ChrisJBurns

@ChrisJBurns ChrisJBurns commented Aug 10, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • We have no static analysis for our own workflows. security-scan.yml runs Grype and govulncheck, which cover our dependencies and our Go code — nothing looks at .github/ itself, so workflow anti-patterns accumulate with no signal. This adds zizmor as a job in the existing security scan.
  • Every security scan was running twice per PR. security-scan.yml has its own pull_request trigger and was called as a reusable workflow from run-on-pr.yml, so Grype and govulncheck each ran two full times on every pull request. The same overlap existed on main, between the push: trigger and the call from run-on-main.yml. This keeps exactly one path each and reclaims the duplicate runs.

zizmor is deliberately advisory to start with. It reports 111 findings against the current tree, and gating on that today would just block every PR. --no-exit-codes stops findings failing the job and continue-on-error stops a tool or network failure doing so; both come off once the backlog is worked through, which is inventoried in #6253.

Closes #6250

Type of change

  • Bug fix
  • New feature
  • Refactoring (no behavior change)
  • Dependency update
  • Documentation
  • Other (describe): CI configuration

Test plan

  • Unit tests (task test)
  • E2E tests (task test-e2e)
  • Linting (task lint-fix)
  • Manual testing (describe below)

No Go code changes, so the repo's own test tasks aren't meaningful here. What was verified locally:

  • actionlint passes clean on both changed files.
  • Both files parse as YAML.
  • zizmor 1.29.0 runs to completion against .github/ and emits valid SARIF, exit code 0 with --no-exit-codes despite 111 findings.
  • Confirmed nothing in run-on-pr.yml had needs: security-scan, so removing that job strands nothing.
  • Confirmed run-on-main.yml still calls the workflow and image-build-and-push still gates on it via needs, so the main-branch path is unchanged.
  • Confirmed via the branch protection and ruleset APIs that the only required status check is CRD Schema Compatibility — moving which workflow reports the security scan won't leave PRs waiting on a check that never runs.
  • pipx is present on the ubuntu-24.04 runner image, so no extra setup action is needed.

The zizmor job itself won't run on this PR — security-scan.yml has to be on the base branch before its pull_request trigger applies. Its first execution will be post-merge, or via workflow_dispatch from this branch if you'd like to see it before approving.

Does this introduce a user-facing change?

No.

Special notes for reviewers

  • Findings are never printed. Workflow logs and job summaries are world-readable on a public repo, so the run writes SARIF straight to a file and uploads it to the Security tab, which requires write access to read. Worth preserving if this step is ever edited. Note this isn't secrecy for its own sake — .github/ is public and zizmor is open source, so anyone can already run it against us; it just avoids handing over a pre-baked report.
  • The SARIF upload is skipped for fork PRs, whose token is read-only and can't write security events. Those workflows are still scanned on push to main.
  • pull_request is intentionally unfiltered by branch. security-scan.yml's own trigger was branches: [main], but run-on-pr.yml fired on all PRs — leaving the filter in place would have quietly narrowed coverage.
  • The new upload-sarif line copies the existing pin from the Grype job. That pin's # v4 comment doesn't match a real tag, which zizmor itself flags; left consistent with the existing line rather than fixed inline, and tracked in zizmor findings backlog: pins, expressions and checkout credentials #6253. (Since fixed on this branch — see below.)

Generated with Claude Code

ChrisJBurns and others added 2 commits August 10, 2026 16:47
security-scan.yml has its own pull_request trigger and was also called
as a reusable workflow from run-on-pr.yml, so Grype and govulncheck ran
twice for every PR. Drop the call from run-on-pr.yml and let the direct
trigger cover PRs; its branch filter is removed so coverage matches what
run-on-pr.yml gave.

The same duplication existed on main, where the push: trigger overlapped
with the call from run-on-main.yml. That call is kept, because
image-build-and-push gates on its result, and the push: trigger is
dropped instead.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Grype and govulncheck cover our dependencies and our Go code, but
nothing checks the workflows themselves, so anti-patterns accumulate
with no signal.

Advisory to start with: --no-exit-codes stops findings failing the job
and continue-on-error stops a tool or network failure doing so, while
the existing backlog is worked through. Both come off once it can gate.

Findings are written straight to SARIF and never printed. Workflow logs
and job summaries are world-readable on a public repository, so echoing
them would publish them; the SARIF upload keeps them in the Security
tab. The upload is skipped for fork PRs, whose token is read-only.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ChrisJBurns
ChrisJBurns requested a review from JAORMX as a code owner August 10, 2026 15:51
@github-advanced-security

Copy link
Copy Markdown
Contributor

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.

Comment thread .github/workflows/security-scan.yml Fixed
Comment thread .github/workflows/security-scan.yml Fixed
@github-actions github-actions Bot added the size/XS Extra small PR: < 100 lines changed label Aug 10, 2026
@github-actions github-actions Bot added size/XS Extra small PR: < 100 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Aug 10, 2026
The zizmor job's checkout now sets persist-credentials: false — it only
reads workflow files and never pushes, so leaving the token in
.git/config served no purpose.

Both upload-sarif pins move to the commit the v4 tag actually points at.
They were pinned to f205ea1c, which is a releases/v4 branch commit
(v4.37.4) that no tag references, so the trailing "# v4" comment was
misleading and the pin was 56 commits behind v4. The Grype job's pin is
updated alongside the new one so the two agree.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added size/XS Extra small PR: < 100 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Aug 10, 2026
@codecov

codecov Bot commented Aug 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 72.75%. Comparing base (63f32f3) to head (18a8cea).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #6251      +/-   ##
==========================================
+ Coverage   72.72%   72.75%   +0.03%     
==========================================
  Files         742      742              
  Lines       77281    77299      +18     
==========================================
+ Hits        56199    56238      +39     
+ Misses      17122    17080      -42     
- Partials     3960     3981      +21     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions Bot added size/XS Extra small PR: < 100 lines changed and removed size/XS Extra small PR: < 100 lines changed labels Aug 10, 2026
@ChrisJBurns
ChrisJBurns merged commit 991fdce into main Aug 10, 2026
49 of 50 checks passed
@ChrisJBurns
ChrisJBurns deleted the harden-actions-workflows-zizmor branch August 10, 2026 16:16
ChrisJBurns added a commit that referenced this pull request Aug 10, 2026
The Grype and govulncheck jobs only read the tree — anchore/scan-action
scans the filesystem and govulncheck-action runs with repo-checkout
false — so neither needs the token left in .git/config.

These were held back from the previous commit only because #6251 also
edits this file. A trial merge of the two branches is clean, so there is
no reason to defer them further.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ChrisJBurns added a commit that referenced this pull request Aug 10, 2026
The Grype and govulncheck jobs only read the tree — anchore/scan-action
scans the filesystem and govulncheck-action runs with repo-checkout
false — so neither needs the token left in .git/config.

These were held back from the previous commit only because #6251 also
edits this file. A trial merge of the two branches is clean, so there is
no reason to defer them further.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
ChrisJBurns added a commit that referenced this pull request Aug 10, 2026
* Stop persisting git credentials in CI checkouts

actions/checkout writes the job token into .git/config and leaves it
there for the rest of the job unless told otherwise. None of these jobs
push, so the credential is available to every subsequent step and every
tool they invoke for no reason.

Covers the CI workflows only. Excluded: the release workflows, which no
pull request can exercise; the three running claude-code-action, which
has broad shell access and may need to push; api-compat.yml, which does
a `git fetch` and is the repository's only required status check; and
security-scan.yml, whose checkout is handled in the zizmor PR.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

* Stop persisting credentials in security scan checkouts

The Grype and govulncheck jobs only read the tree — anchore/scan-action
scans the filesystem and govulncheck-action runs with repo-checkout
false — so neither needs the token left in .git/config.

These were held back from the previous commit only because #6251 also
edits this file. A trial merge of the two branches is clean, so there is
no reason to defer them further.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot mentioned this pull request Aug 14, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XS Extra small PR: < 100 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Harden GitHub Actions workflows and adopt zizmor in CI

3 participants