Skip to content

fix(ci): GitHub Actions security hardening#2009

Open
stevebeattie wants to merge 4 commits into
wolfi-dev:mainfrom
stevebeattie:security/psec-923-wolfictl
Open

fix(ci): GitHub Actions security hardening#2009
stevebeattie wants to merge 4 commits into
wolfi-dev:mainfrom
stevebeattie:security/psec-923-wolfictl

Conversation

@stevebeattie

Copy link
Copy Markdown
Member

This PR applies GitHub Actions hardening fixes across the workflows in
.github/workflows/, surfaced by static analysis (zizmor).

What this changes

  • persist-credentials: false on checkout steps that don't push back to the
    repo, so the auto-persisted GITHUB_TOKEN isn't left in .git/config.
  • Repo-level zizmor config disabling cosmetic pedantic-only rules, plus a
    dependabot-cooldown threshold.
  • Harden cd handling in the composite-action build step (quote/guard the
    directory change so a failed cd can't run subsequent commands in the wrong
    place).
  • Disable the Go build/module cache on the signed-release flow
    (cache: false on actions/setup-go in release.yaml). That workflow runs
    goreleaser to sign and publish; setup-go's cache bundles the verified module
    cache with the unverified ~/.cache/go-build, and PR-reachable build workflows
    write the same key scheme — so a poisoned build cache could be restored into
    the signed release. Releases are infrequent, so a clean rebuild is the right
    default.

Test plan

  • zizmor .github/ — the release-flow cache-poisoning finding is resolved.
  • actionlint — workflows still parse with no errors.

Refs: PSEC-923

Add explicit persist-credentials: false to every actions/checkout step
flagged by zizmor's artipacked rule. Each site was traced per the
artipacked decision tree: no downstream step relies on the persisted
GITHUB_TOKEN credential store.

- .github/actions/action.yaml: composite build step does no git writes.
- build-goreleaser.yaml: goreleaser --snapshot --skip=publish,sign; no
  git writes; GITHUB_TOKEN passed to goreleaser via env.
- build.yaml (wolfi-dev/os checkout): read-only 'wolfictl text' consumer.
- release.yaml: git-tag push and goreleaser both receive the octo-sts
  token explicitly (token:/GITHUB_TOKEN env), not via the credential store.

Refs: PSEC-923
Generated-By: claude-guard chain f243303487c2f171f5dcf269592ab825
Skills-Applied: artipacked
Skills-Sha: d1a637a7f238e262da2698fbdbfd84d56a645e4cf4c63cdfcb3347544f7f2967
Image-Sha: sha256:3b5a6a2d7ac0edcd1da9473f63aef0922371ae7094a2583f4faa5bdef838bc1f
Address the pedantic-persona cosmetic and dependabot-cooldown findings
centrally via .github/zizmor.yml, per the zizmor-config recipe.

- Add .github/zizmor.yml: disable the cosmetic pedantic-only rules
  (anonymous-definition, undocumented-permissions, concurrency-limits)
  and set dependabot-cooldown threshold to 3 days.
- Add cooldown.default-days: 3 to both ecosystems in dependabot.yml
  (github-actions, gomod) to match the zizmor threshold; both files are
  required to clear the dependabot-cooldown finding.
- Extend the Zizmor workflow pull_request/push paths to include
  .github/dependabot.yml and .github/zizmor.yml so config edits re-run
  the check.

Refs: PSEC-923
Generated-By: claude-guard chain f243303487c2f171f5dcf269592ab825
Skills-Applied: zizmor-config
Skills-Sha: d1a637a7f238e262da2698fbdbfd84d56a645e4cf4c63cdfcb3347544f7f2967
Image-Sha: sha256:3b5a6a2d7ac0edcd1da9473f63aef0922371ae7094a2583f4faa5bdef838bc1f
Wrap the build step's directory change in a subshell and add an
explicit failure guard, per the shellcheck-suppress recipe's fix-order
(fix the shell code first):

- SC2164: 'cd wolfictl-setup-gha' now uses '|| exit' so a failed cd does
  not silently run make/mv in the wrong directory.
- SC2103: replacing 'cd ..' with a subshell avoids the stateful
  round-trip; the subsequent 'rm -rf wolfictl-setup-gha' runs from the
  original working directory. Behavior is unchanged.

Refs: PSEC-923
Generated-By: claude-guard chain f243303487c2f171f5dcf269592ab825
Skills-Applied: shellcheck-suppress
Skills-Sha: d1a637a7f238e262da2698fbdbfd84d56a645e4cf4c63cdfcb3347544f7f2967
Image-Sha: sha256:3b5a6a2d7ac0edcd1da9473f63aef0922371ae7094a2583f4faa5bdef838bc1f
release.yaml is a signed-release path (goreleaser sign + publish, id-token:write).
actions/setup-go's cache bundles the verified module cache with the unverified
~/.cache/go-build, and PR-reachable build workflows write the same key scheme, so
a poisoned build cache could be restored into the signed release. Set cache:false;
releases are infrequent so a clean rebuild is the right default.

Generated-By: claude-guard
@stevebeattie stevebeattie requested review from egibs and eslerm July 2, 2026 05:18
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