Skip to content

ci: add zizmor workflow audit - #89

Open
oc-tmueller wants to merge 2 commits into
mainfrom
ci/zizmor
Open

oc-tmueller wants to merge 2 commits into
mainfrom
ci/zizmor

Conversation

@oc-tmueller

Copy link
Copy Markdown
Contributor

Adds a zizmor audit of this repository's GitHub Actions workflows and Dependabot config, through the reusable owncloud/reusable-workflows/.github/workflows/zizmor.yml (owncloud/reusable-workflows#104). It's part of an org-wide rollout. Once the repo PRs have landed, Zizmor / Zizmor becomes a required check through owncloud/admin.

  • Behaviour: any finding, at any severity, fails the check, with an annotation on the offending line. The check runs on every PR, on pushes to main and weekly, because online audits such as known-vulnerable actions can start failing without a code change.
  • Permissions: contents: read only, so it also works on fork PRs.
  • Config: owncloud/* references may stay on @main. Everything else must be SHA-pinned.

Existing findings fixed (separate commits)

  • github-app: each codesign-bot App token requests only what its binary uses (traced through internal/ghclient/rest, internal/enroll, internal/revoke, cmd/*). Before, each inherited every permission of the installation.
    • issuer and revoker: contents: write + issues: write. They list, comment on, label and close request issues, and write the ledger through the Contents API.
    • privrevoke: contents: write, for the ledger only.
    • crlgen: contents: write, for the CRL only.
    • The access probe (GET /repos/{r}) needs only metadata: read, which every scoped App token gets automatically.
  • github-app (owner:), suppressed inline: the issuer token stays org-wide because the target app repos are only known at runtime ([cert] files_classifier #35).
  • dangerous-triggers, suppressed inline: crl's workflow_run re-runs main's own crlgen after a revocation and reads no artifact, ref or input from the triggering run.
  • artipacked: checkouts do not persist credentials. Nothing runs git after checkout. Ledger and CRL writes go through the Contents API, and go run needs only public modules.
  • dependabot-cooldown: gomod updates wait 7 days, as github-actions already does.

The App-token steps only run on the schedule, issue events or dispatch, so this PR's CI doesn't exercise them. Every requested permission is one the bots already use today.

For the maintainers (pre-existing, not changed here)

  • The issuer's org-wide token now carries contents: write + issues: write on every repo the App is installed on. It is handed to a bot that parses issue bodies. Two tokens would bound that: a repo-scoped one with write on this repo, and an owner-scoped one with only permission-contents: read for target-repo reads. That split needs a change in cmd/issuer.
  • crl regenerates, signs and commits after every completed revocation run. That includes no-op 10-minute scheduled runs and runs triggered by anyone's issue events. main holds about 7.7k "chore: regenerate crl/developers.crl" commits. Gating on an actual ledger change would cut the Vault signing operations and commits. So would dropping workflow_run and regenerating inline after a revocation.
  • crl's workflow_run has no branches: [main] filter. A privileged-revocation dispatched from a feature branch therefore also triggers a production CRL publish.

zizmor 1.31.1 reports no findings on this branch.

🤖 Generated with Claude Code

oc-tmueller and others added 2 commits October 26, 2026 14:43
Runs zizmor over this repository's workflows and Dependabot config on
every pull request, on pushes to the default branch and weekly, through
owncloud/reusable-workflows' zizmor.yml. Any finding fails the check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com>
- github-app: each codesign-bot App token requests only what its binary
  uses, instead of inheriting every permission of the installation:
  issuer and revoker read/close/comment on/label request issues and
  write the ledger (contents + issues write); privrevoke only reads and
  writes the ledger, and crlgen the CRL (contents write). The issuer's
  org-wide owner: scope stays, suppressed inline: target app repos are
  only known at runtime (issue #35).
- dangerous-triggers: crl's workflow_run trigger is suppressed inline.
  It re-runs main's own crlgen after a revocation and reads no
  artifact, ref or input from the triggering run.
- artipacked: checkouts do not persist credentials. Nothing runs git
  after checkout; ledger and CRL writes go through the Contents API.
- dependabot-cooldown: gomod updates wait 7 days, as github-actions
  already does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Signed-off-by: Thomas Müller <323649642+oc-tmueller@users.noreply.github.com>
@oc-tmueller
oc-tmueller requested a review from a team as a code owner October 26, 2026 13:46

This branch has not been deployed

No deployments
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.

1 participant