From f443bd29ad48e37372edfa902d6cb1d254cea840 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Wed, 2 Sep 2026 19:22:17 +0200 Subject: [PATCH] ci: harden GitHub Actions workflows and add zizmor scan Add a CI job that runs the zizmor static analyzer over the workflow files under .github/ to audit for supply-chain and privilege-escalation weaknesses (unpinned actions, credential persistence, template injection, and overly broad GITHUB_TOKEN permissions). Also apply the corresponding hardening to existing workflows: - add persist-credentials: false to all actions/checkout steps - narrow top-level `permissions: read-all` to `contents: read` - move github.event.inputs.tag into an env var in backfill-docs to avoid template injection in a run block - fix a malformed version-pin comment for mshick/add-pr-comment - add a 7-day cooldown to dependabot updates --- .github/dependabot.yml | 4 ++ .github/workflows/backfill-docs.yml | 7 +++- .github/workflows/conda-package-cf.yml | 5 ++- .github/workflows/conda-package.yml | 7 +++- .github/workflows/generate-coverage.yaml | 4 +- .github/workflows/generate-docs.yml | 7 ++-- .github/workflows/openssf-scorecard.yml | 3 +- .github/workflows/os-llvm-sycl-build.yml | 4 +- .github/workflows/pre-commit.yml | 4 +- .../workflows/run-tests-from-dppy-bits.yaml | 3 +- .github/workflows/zizmor.yml | 39 +++++++++++++++++++ 11 files changed, 75 insertions(+), 12 deletions(-) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 62ec4a7945..f86275e2b1 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,8 @@ updates: schedule: interval: "weekly" day: "saturday" + cooldown: + default-days: 7 labels: ["autoupdate"] groups: github-actions: @@ -15,6 +17,8 @@ updates: schedule: interval: "weekly" day: "saturday" + cooldown: + default-days: 7 labels: ["autoupdate"] groups: pre-commit: diff --git a/.github/workflows/backfill-docs.yml b/.github/workflows/backfill-docs.yml index 852e189da6..0a77d7d963 100644 --- a/.github/workflows/backfill-docs.yml +++ b/.github/workflows/backfill-docs.yml @@ -7,7 +7,8 @@ on: required: true type: string -permissions: read-all +permissions: + contents: read env: CHECK_CONFIG_SCRIPT: "import sys; from packaging.version import parse; print('true' if parse('0.17.0') <= parse(sys.argv[1]) < parse('0.22.0') else 'false')" @@ -67,8 +68,10 @@ jobs: persist-credentials: false - name: Inject new docs configuration shell: bash -l {0} + env: + TAG: ${{ github.event.inputs.tag }} run: | - NEEDS_CONFIG=$(python -c "${{ env.CHECK_CONFIG_SCRIPT }}" "${{ github.event.inputs.tag }}") + NEEDS_CONFIG=$(python -c "$CHECK_CONFIG_SCRIPT" "$TAG") if [[ "${NEEDS_CONFIG}" == "true" ]]; then git fetch origin master diff --git a/.github/workflows/conda-package-cf.yml b/.github/workflows/conda-package-cf.yml index b0e4b0779b..d64ee153c8 100644 --- a/.github/workflows/conda-package-cf.yml +++ b/.github/workflows/conda-package-cf.yml @@ -6,7 +6,8 @@ on: - master pull_request: -permissions: read-all +permissions: + contents: read env: PACKAGE_NAME: dpctl @@ -41,6 +42,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Set pkgs_dirs @@ -109,6 +111,7 @@ jobs: # the recipe takes the version from git describe - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 121a0cae38..3cce876e44 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -6,7 +6,8 @@ on: - master pull_request: -permissions: read-all +permissions: + contents: read env: PACKAGE_NAME: dpctl @@ -41,6 +42,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Set pkgs_dirs @@ -118,6 +120,7 @@ jobs: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - uses: conda-incubator/setup-miniconda@8ee1f361103df19b6f8c8655fd3967a8ecb162d5 # v4.0.1 @@ -618,6 +621,7 @@ jobs: - name: Checkout dpctl repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Download artifact uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 @@ -788,6 +792,7 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false repository: IntelPython/devops-tools fetch-depth: 0 diff --git a/.github/workflows/generate-coverage.yaml b/.github/workflows/generate-coverage.yaml index a66af86c31..72da636288 100644 --- a/.github/workflows/generate-coverage.yaml +++ b/.github/workflows/generate-coverage.yaml @@ -4,7 +4,8 @@ on: push: branches: [master] -permissions: read-all +permissions: + contents: read jobs: generate-coverage: @@ -82,6 +83,7 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Install Lcov diff --git a/.github/workflows/generate-docs.yml b/.github/workflows/generate-docs.yml index d247eae202..1a7efad084 100644 --- a/.github/workflows/generate-docs.yml +++ b/.github/workflows/generate-docs.yml @@ -6,7 +6,8 @@ on: pull_request: types: [opened, synchronize, reopened, closed] -permissions: read-all +permissions: + contents: read jobs: build-and-deploy: @@ -143,7 +144,7 @@ jobs: if: ${{ github.event.pull_request && !github.event.pull_request.head.repo.fork && github.event.action != 'closed' }} env: PR_NUM: ${{ github.event.number }} - uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0.8.3.12.0 + uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0 with: message: | View rendered docs @ https://intelpython.github.io/dpctl/pulls/${{ env.PR_NUM }}/index.html @@ -152,7 +153,7 @@ jobs: if: ${{ github.event.pull_request && !github.event.pull_request.head.repo.fork && github.event.action == 'closed' }} env: PR_NUM: ${{ github.event.number }} - uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0.8.3.12.0 + uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0 with: message: | Deleted rendered PR docs from intelpython.github.com/dpctl, latest should be updated shortly. :crossed_fingers: diff --git a/.github/workflows/openssf-scorecard.yml b/.github/workflows/openssf-scorecard.yml index b1399eddce..095f38b960 100644 --- a/.github/workflows/openssf-scorecard.yml +++ b/.github/workflows/openssf-scorecard.yml @@ -16,7 +16,8 @@ on: branches: [ "master" ] # Declare default permissions as read only. -permissions: read-all +permissions: + contents: read jobs: analysis: diff --git a/.github/workflows/os-llvm-sycl-build.yml b/.github/workflows/os-llvm-sycl-build.yml index 028ea022d5..9fb6f3a295 100644 --- a/.github/workflows/os-llvm-sycl-build.yml +++ b/.github/workflows/os-llvm-sycl-build.yml @@ -4,7 +4,8 @@ on: push: branches: [master] -permissions: read-all +permissions: + contents: read jobs: install-compiler: @@ -128,6 +129,7 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Create set_allvars.sh diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 2e72ebf2ba..090c8bc614 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -5,7 +5,8 @@ on: push: branches: [master] -permissions: read-all +permissions: + contents: read jobs: pre-commit: @@ -18,6 +19,7 @@ jobs: - name: Checkout dpctl uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false ref: ${{ github.sha }} # use hash to pass no-commit-to-branch check - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: diff --git a/.github/workflows/run-tests-from-dppy-bits.yaml b/.github/workflows/run-tests-from-dppy-bits.yaml index dde952d928..676f4a7e7c 100644 --- a/.github/workflows/run-tests-from-dppy-bits.yaml +++ b/.github/workflows/run-tests-from-dppy-bits.yaml @@ -9,7 +9,8 @@ on: - cron: '28 2 * * *' workflow_dispatch: -permissions: read-all +permissions: + contents: read env: MODULE_NAME: dpctl diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000000..2297970ce7 --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,39 @@ +name: Security scan of GitHub Actions workflows (zizmor) + +on: + push: + branches: + - master + pull_request: + +permissions: {} + +concurrency: + group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + cancel-in-progress: true + +jobs: + zizmor: + name: Scan GitHub Actions workflows + + runs-on: ubuntu-latest + timeout-minutes: 10 + + permissions: + contents: read # needed to clone the repo + + steps: + - name: Checkout dpctl repo + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@70fb788f84895a7701f5643d103d587e460b5c99 # v0.6.3 + with: + # Low/informational template-injection notes come from internally-defined + # values (no external input), so they are reported as annotations but do not gate CI + min-severity: medium + advanced-security: false + annotations: true + inputs: .github/