Skip to content

ci: harden test.yaml and docs.yaml for zizmor - #767

Open
tyler-reitz wants to merge 1 commit into
mainfrom
chore/harden-workflows
Open

ci: harden test.yaml and docs.yaml for zizmor#767
tyler-reitz wants to merge 1 commit into
mainfrom
chore/harden-workflows

Conversation

@tyler-reitz

Copy link
Copy Markdown
Contributor

Split out of #766 at @jhuleatt's request, so that PR can stay focused on the release checks. Covers docs.yaml too, as he asked.

This is a pre-existing, repo-wide condition rather than anything #766 introduced. The zizmor scan only runs when a workflow file changes, so it fires against whatever state the file was already in.

Changes

  • All 14 action references pinned to commit SHAs, with the resolved release in a trailing comment so versions stay legible and Dependabot can still bump them. Clears unpinned-uses, the only mandatory audit.
  • Top-level permissions: contents: read on both workflows. Neither writes to the repo through GITHUB_TOKEN; the publish job authenticates to npm separately. Clears excessive-permissions.
  • persist-credentials: false on all four checkouts. The token is not needed after the clone, and leaving it in .git/config exposes it to every later step. Clears artipacked.

Result

Measured with the version CI pins (1.25.2):

Before After
test.yaml 8 medium, 17 high 0 medium, 5 high
docs.yaml 2 medium, 2 high no findings

CI fails on Medium or higher, so partial fixes would not clear it.

The 5 remaining findings on test.yaml are all cache-poisoning, which the org scan suppresses. Fixing those means restructuring how the workflow caches around the publish path, which does not belong here.

Notes

No functional change to any job. 32 lines across two files.

Verified that main's switch of the publish registry to wombat-dressing-room.appspot.com (fcbfe83) is preserved, since the pinning touches that same setup-node block.

🤖 Generated with Claude Code

Split out of #766 at Jeff's request, so that PR can stay focused on the release
checks. This is a pre-existing, repo-wide condition rather than anything the
gate introduced: the zizmor scan only runs when a workflow file changes, so it
fires against whatever state the file was already in.

Both workflows, since he asked for docs.yaml too:

- **All 14 action references pinned to commit SHAs**, with the resolved release
  in a trailing comment so versions stay legible and Dependabot can still bump
  them. Clears `unpinned-uses`, the only mandatory audit.
- **Top-level `permissions: contents: read`.** Neither workflow writes to the
  repo through GITHUB_TOKEN; the publish job authenticates to npm separately,
  now via the Google npm service. Clears `excessive-permissions`.
- **`persist-credentials: false` on all four checkouts.** The token is not
  needed after the clone, and leaving it in .git/config exposes it to every
  later step. Clears `artipacked`.

Result, measured with the version CI pins (1.25.2):

    test.yaml   8 medium, 17 high  ->  0 medium, 5 high
    docs.yaml   2 medium,  2 high  ->  no findings at all

CI fails on Medium or higher, so partial fixes would not have cleared it. The 5
remaining findings on test.yaml are all `cache-poisoning`, which the org scan
suppresses; fixing those means restructuring how the workflow caches around the
publish path and does not belong here.

No functional change to any job. Verified that main's switch of the publish
registry to wombat-dressing-room is preserved.
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@armando-navarro armando-navarro left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for splitting this out, Tyler. It made the SHA changes easy to review on their own. I went through the security-relevant claims against the actions' upstream tags and the full workflow files, and everything checks out.

What I verified

  • All 14 references (6 unique actions) are locked to commit SHAs that resolve exactly to the version in each trailing comment. I dereferenced each tag through the GitHub API: checkout 11d5960 = v4.4.0, setup-node 49933ea = v4.4.0, upload-artifact ea165f8 = v4.6.2, setup-java c1e3236 = v4.8.0, cache 0057852 = v4.3.0, download-artifact d3f86a1 = v4.3.0. No mismatches.
  • permissions: contents: read is sufficient. No job writes to the repo through GITHUB_TOKEN, and publish authenticates to npm with NODE_AUTH_TOKEN against wombat-dressing-room.appspot.com, which is preserved from fcbfe83.
  • persist-credentials: false is safe on all four checkouts. The publish job correctly has no checkout, and docs.yaml's closing git diff --exit-code is a local operation that needs no token. There are also no git+/GitHub dependencies in package.json, so npm ci won't need the credentials you dropped.
  • Staying on the v4 line reads as the right call here. The newer majors (v5 through v8) could bring breaking changes, and this PR is about locking the versions in place, not upgrading them.

One optional follow-up

I noticed there's no .github/dependabot.yml in the repo.

  • The version comments are exactly the format Dependabot reads, so the SHAs are ready for it, but as I understand it routine version bumps for the github-actions ecosystem only fire once that config exists.
  • Without it these SHAs would need manual bumping and could drift over time.
  • Would it be worth adding a small github-actions entry in a follow-up so the "Dependabot can still bump them" benefit actually kicks in?
  • Happy to open that myself if you'd rather keep this PR focused.

If I've misread any of the above, point me at it and I'll take another look. Otherwise this is good to go from my side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants