From 482f8bd2eb8ec36ce69518df7fd2290a9a528805 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Fri, 22 May 2026 12:00:34 +0200 Subject: [PATCH 01/12] Add zizmor github action --- .github/workflows/zizmor.yaml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 .github/workflows/zizmor.yaml diff --git a/.github/workflows/zizmor.yaml b/.github/workflows/zizmor.yaml new file mode 100644 index 00000000..953fe28b --- /dev/null +++ b/.github/workflows/zizmor.yaml @@ -0,0 +1,25 @@ +name: GitHub Actions Security Analysis with zizmor 🌈 + +on: + push: + branches: ["main"] + pull_request: + branches: ["**"] + +permissions: {} + +jobs: + zizmor: + runs-on: ubuntu-latest + permissions: + security-events: write + # contents: read # only needed for private or internal repos + # actions: read # only needed for private or internal repos + steps: + - name: Checkout repository + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false + + - name: Run zizmor 🌈 + uses: zizmorcore/zizmor-action@b572f7b1a1c2d41efaab43d504f68d215c3cd727 # v0.5.4 From 81a77941256182a3917fe5400e9f94a161b5fcb1 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Fri, 22 May 2026 12:17:19 +0200 Subject: [PATCH 02/12] Pin 3rd-party github actions to commit hashes --- .github/workflows/ci.yml | 26 +++++++++++++------------- .github/workflows/ci_upstream.yml | 16 ++++++++-------- .github/workflows/docs.yml | 7 ++++--- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 14fd9a8b..33c677d8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,18 +27,18 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - uses: actions/setup-python@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" - - uses: pre-commit/action@v3.0.1 + - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1 check-manifest: # check-manifest is a tool that checks that all files in version control are # included in the sdist (unless explicitly excluded) runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - run: pipx run check-manifest setup: @@ -65,16 +65,16 @@ jobs: include: ${{ fromJson(needs.setup.outputs.matrix) }} steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 🔧 Set up pixi - uses: prefix-dev/setup-pixi@v0.9.5 + uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5 with: environments: ${{ matrix.environment }} - name: Restore shared data cache id: cache-data - uses: actions/cache@v5 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: data/ key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" @@ -87,7 +87,7 @@ jobs: # If something goes wrong with scheduled tests, open an issue in the repo - name: 📝 Report Failures if: failure() && github.event_name == 'schedule' - uses: JasonEtco/create-an-issue@v2 + uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PLATFORM: ${{ matrix.platform }} @@ -100,7 +100,7 @@ jobs: - name: Coverage if: success() && matrix.platform == 'ubuntu-latest' - uses: codecov/codecov-action@v6 + uses: codecov/codecov-action@e79a6962e0d4c0c17b229090214935d2e33f8354 # v6.0.1 with: token: ${{ secrets.CODECOV_TOKEN }} files: /home/runner/work/ngio/ngio/coverage.xml @@ -119,12 +119,12 @@ jobs: contents: write steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - name: 🐍 Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.x" cache: "pip" @@ -136,9 +136,9 @@ jobs: python -m build - name: 🚢 Publish to PyPI - uses: pypa/gh-action-pypi-publish@release/v1 + uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0 - - uses: softprops/action-gh-release@v3 + - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 with: generate_release_notes: true files: "./dist/*" diff --git a/.github/workflows/ci_upstream.yml b/.github/workflows/ci_upstream.yml index 99cc49a2..5615b2ef 100644 --- a/.github/workflows/ci_upstream.yml +++ b/.github/workflows/ci_upstream.yml @@ -30,10 +30,10 @@ jobs: github.event.workflow_run.conclusion == 'success' steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 🐍 Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" cache: "pip" @@ -45,7 +45,7 @@ jobs: python -m pip install .[test] - name: Restore shared data cache - uses: actions/cache@v5 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: data/ key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" @@ -57,7 +57,7 @@ jobs: - name: 📝 Report Failures if: failure() && github.event_name == 'schedule' - uses: JasonEtco/create-an-issue@v2 + uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PLATFORM: ubuntu-latest @@ -77,10 +77,10 @@ jobs: github.event.workflow_run.conclusion == 'success' steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - name: 🐍 Set up Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" cache: "pip" @@ -92,7 +92,7 @@ jobs: python -m pip install .[test] --pre - name: Restore shared data cache - uses: actions/cache@v5 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: data/ key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" @@ -104,7 +104,7 @@ jobs: - name: 📝 Report Failures if: failure() - uses: JasonEtco/create-an-issue@v2 + uses: JasonEtco/create-an-issue@1b14a70e4d8dc185e5cc76d3bec9eab20257b2c5 # v2.9.2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} PLATFORM: ubuntu-latest diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f0a8244a..d0c874d5 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -22,12 +22,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 + persist-credentials: true # TODO: is this needed? - name: 🔧 Set up pixi - uses: prefix-dev/setup-pixi@v0.9.5 + uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5 with: environments: docs @@ -37,7 +38,7 @@ jobs: git config --local user.name "github-actions[bot]" - name: Restore shared data cache - uses: actions/cache@v5 + uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 with: path: data/ key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" From a7cd9570dda74bcb3ec21227e8085d7ec2c2e34f Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Fri, 22 May 2026 12:17:33 +0200 Subject: [PATCH 03/12] Setup quarterly update of 3rd-party github actions --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 96505a93..fd02c603 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -8,3 +8,9 @@ updates: interval: "weekly" commit-message: prefix: "ci(dependabot):" + - package-ecosystem: github-actions + directory: /.github/workflows + schedule: + interval: "quarterly" + cooldown: + default-days: 7 From 36facfe10c8a050eef0eefb11ac929d6aa9e7a80 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Fri, 22 May 2026 12:21:17 +0200 Subject: [PATCH 04/12] Do not use cache when publishing package See https://docs.zizmor.sh/audits/#cache-poisoning --- .github/workflows/ci.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 33c677d8..2ea36729 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -127,8 +127,6 @@ jobs: uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.x" - cache: "pip" - cache-dependency-path: "pyproject.toml" - name: 👷 Build run: | From cdc7e1ae8e5fb8d163bbcbe4fe674979928fe5db Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Fri, 22 May 2026 13:34:39 +0200 Subject: [PATCH 05/12] First attempt towards `ci_upstream` permissions --- .github/workflows/ci_upstream.yml | 14 ++++++++++++++ .github/workflows/docs.yml | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/.github/workflows/ci_upstream.yml b/.github/workflows/ci_upstream.yml index 5615b2ef..15bd118a 100644 --- a/.github/workflows/ci_upstream.yml +++ b/.github/workflows/ci_upstream.yml @@ -20,10 +20,16 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: test-pip: name: pip (stable) runs-on: ubuntu-latest + permissions: + contents: read + issues: write + # For workflow_run: only proceed if the main CI succeeded if: > github.event_name != 'workflow_run' || @@ -31,6 +37,8 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true # TODO: set to false and check if it is needed - name: 🐍 Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -71,6 +79,10 @@ jobs: test-pip-pre: name: pip (--pre) runs-on: ubuntu-latest + permissions: + contents: read + issues: write + # For workflow_run: only proceed if the main CI succeeded if: > github.event_name != 'workflow_run' || @@ -78,6 +90,8 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: true # TODO: set to false and check if it is needed - name: 🐍 Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d0c874d5..d258912f 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -21,6 +21,11 @@ jobs: name: Deploy Docs runs-on: ubuntu-latest + permissions: + contents: read + pages: write + # TODO: anything else? + steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: From 0c8f19cbc50873ee623427e829937158fcbef83a Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:27:32 +0200 Subject: [PATCH 06/12] Pin `check-manifest` version --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ea36729..7131261b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,7 +39,7 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - run: pipx run check-manifest + - run: pipx run --spec check-manifest==0.51 check-manifest setup: # Outputs a reduced matrix for PRs, full matrix for main/tags/schedule From e3ad3d70d20dc785d26c12e2836e485aa37f28fd Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:33:57 +0200 Subject: [PATCH 07/12] Comment out caching step from docs action --- .github/workflows/docs.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index d258912f..37ee20f6 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -24,7 +24,6 @@ jobs: permissions: contents: read pages: write - # TODO: anything else? steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 @@ -42,13 +41,14 @@ jobs: git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - - name: Restore shared data cache - uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - with: - path: data/ - key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" - restore-keys: | - "${{ runner.os }}-data-" + # TODO: Check whether this cache is actually used for building the docs + # - name: Restore shared data cache + # uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 + # with: + # path: data/ + # key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" + # restore-keys: | + # "${{ runner.os }}-data-" - name: Deploy docs run: | From 356e216c14d08d182cddfc46c67af4e5ea9909c8 Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:45:32 +0200 Subject: [PATCH 08/12] Permissions for ci.yml --- .github/workflows/ci.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7131261b..4acfac18 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,11 +23,15 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true +permissions: {} + jobs: lint: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 with: python-version: "3.13" @@ -39,6 +43,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - run: pipx run --spec check-manifest==0.51 check-manifest setup: @@ -63,9 +69,14 @@ jobs: fail-fast: false matrix: include: ${{ fromJson(needs.setup.outputs.matrix) }} + permissions: + contents: read + issues: write steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + with: + persist-credentials: false - name: 🔧 Set up pixi uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5 @@ -122,6 +133,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 + persist-credentials: false - name: 🐍 Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 From 7e6112ccc4011b57051d5bc072c1a550268f7fed Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:48:27 +0200 Subject: [PATCH 09/12] CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 773c37fb..6a79e96b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +### Chores +- Harden GitHub Actions and scan workflows through `zizmor`. + ## [v0.5.11] ### Fix From e8f8320811352e2a1613a5e355a0cbaf77f0e67f Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:50:37 +0200 Subject: [PATCH 10/12] dependabot grouping --- .github/dependabot.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fd02c603..33272b1a 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -14,3 +14,8 @@ updates: interval: "quarterly" cooldown: default-days: 7 + groups: + gha-updates: + applies-to: version-updates + patterns: + - '*' From 935d234be2e954723e968c7ab6a02e997dde911c Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:55:24 +0200 Subject: [PATCH 11/12] no persist-credentials --- .github/workflows/ci_upstream.yml | 4 ++-- .github/workflows/docs.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci_upstream.yml b/.github/workflows/ci_upstream.yml index 15bd118a..99f1d1d6 100644 --- a/.github/workflows/ci_upstream.yml +++ b/.github/workflows/ci_upstream.yml @@ -38,7 +38,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - persist-credentials: true # TODO: set to false and check if it is needed + persist-credentials: false - name: 🐍 Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 @@ -91,7 +91,7 @@ jobs: steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: - persist-credentials: true # TODO: set to false and check if it is needed + persist-credentials: false - name: 🐍 Set up Python uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0 diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 37ee20f6..9b1381da 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -29,7 +29,7 @@ jobs: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 with: fetch-depth: 0 - persist-credentials: true # TODO: is this needed? + persist-credentials: false - name: 🔧 Set up pixi uses: prefix-dev/setup-pixi@1b2de7f3351f171c8b4dfeb558c639cb58ed4ec0 # v0.9.5 From 4d52d30f1ca3486144e434d4f5a3c95ee367723f Mon Sep 17 00:00:00 2001 From: Tommaso Comparin <3862206+tcompa@users.noreply.github.com> Date: Mon, 25 May 2026 08:55:40 +0200 Subject: [PATCH 12/12] remove cache for docs github action --- .github/workflows/docs.yml | 9 --------- 1 file changed, 9 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 9b1381da..43b00db4 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -41,15 +41,6 @@ jobs: git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - # TODO: Check whether this cache is actually used for building the docs - # - name: Restore shared data cache - # uses: actions/cache@27d5ce7f107fe9357f9df03efb73ab90386fccae # v5.0.5 - # with: - # path: data/ - # key: "${{ runner.os }}-data-${{ hashFiles('tests/conftest.py') }}" - # restore-keys: | - # "${{ runner.os }}-data-" - - name: Deploy docs run: | VERSION=$(echo $GITHUB_REF | sed 's/refs\/tags\///' | sed 's/refs\/heads\///')