From 8f2b4bed336556926967be7b5bbf67897f6ef6f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C4=81ris=20Pop=C4=93ns?= Date: Thu, 24 Sep 2026 10:03:41 +0000 Subject: [PATCH] chore(ci): harden workflows, enforce zizmor - Explicit read-only `permissions:` on workflows that had none (the org default is read-only already; this makes it visible and drops read access to other scopes). - Checkouts that never push no longer leave the token in .git/config (`persist-credentials: false`); ones that push say so explicitly. - Third-party actions SHA-pinned at the commits their tags point to today; Dependabot keeps them current. - New zizmor job (reusable-actions zizmor.yml) gated by Required checks passed, so new findings block merges; accepted ones are in .github/zizmor.yml. --- .github/workflows/ci.yml | 19 +++++++++++++++++-- .github/workflows/security.yml | 4 ++++ .github/zizmor.yml | 18 ++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 .github/zizmor.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a4f8dec..b5588d6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,9 @@ jobs: md: ${{ steps.filter.outputs.md }} steps: - uses: actions/checkout@v7 - - uses: dorny/paths-filter@v4.0.3 + with: + persist-credentials: false + - uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 id: filter with: filters: | @@ -49,6 +51,8 @@ jobs: runs-on: ubuntu-latest # shellcheck is preinstalled on ubuntu runners steps: - uses: actions/checkout@v7 + with: + persist-credentials: false - name: Run shellcheck run: shellcheck install.sh .chezmoiscripts/run_once_*.sh .chezmoiscripts/run_onchange_*.sh @@ -59,6 +63,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v7 + with: + persist-credentials: false - name: Install shfmt run: brew install shfmt - name: Check formatting @@ -72,6 +78,8 @@ jobs: runs-on: macos-latest steps: - uses: actions/checkout@v7 + with: + persist-credentials: false - name: Install chezmoi + shell linters run: brew install chezmoi shellcheck shfmt - name: Validate templates (minimal flags) @@ -220,16 +228,23 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + with: + persist-credentials: false - uses: DavidAnson/markdownlint-cli2-action@21c1be1b93ad9ed58fa840aacc3f279cde2a72ff # v24.2.0 with: globs: "**/*.md" + # Audit of this repo's own workflows; accepted findings are in + # .github/zizmor.yml. + zizmor: + uses: drumandbytes/reusable-actions/.github/workflows/zizmor.yml@v1 + # Single stable name for the org's required-status-check ruleset to point # at, regardless of how the real jobs above are split or renamed. required-checks-passed: name: Required checks passed runs-on: ubuntu-latest - needs: [changes, shellcheck, shfmt, chezmoi-templates, markdownlint] + needs: [changes, shellcheck, shfmt, chezmoi-templates, markdownlint, zizmor] if: always() steps: - if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 2a8c839..6758248 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -19,6 +19,10 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +# Read-only token; no job here writes to the repo or reads other scopes. +permissions: + contents: read + jobs: security: uses: drumandbytes/reusable-actions/.github/workflows/security-scan.yml@v1 diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 0000000..c9f6ee2 --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,18 @@ +# zizmor configuration, read by the zizmor job in ci.yml. Anything accepted +# here is accepted on purpose -- each entry says why. + +rules: + unpinned-uses: + config: + policies: + # GitHub's own and the org's actions stay on tags (Dependabot moves + # them); third-party actions are SHA-pinned. + "actions/*": ref-pin + "drumandbytes/*": ref-pin + "*": hash-pin + + dangerous-triggers: + ignore: + # workflow_run so Dependabot PRs get a token that can merge; never + # checks out PR code. + - auto-merge.yml