From cecc38692062271a7695d530506ba72ea63539cf Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 11:45:56 +0200 Subject: [PATCH 1/7] ci: add zizmor security scanning for GitHub Actions workflows Add a CI job that runs the zizmor static analyzer over the workflow files under .github/ to catch supply-chain and privilege-escalation weaknesses (unpinned actions, credential persistence, template injection, overly broad permissions). The job runs on pull requests and pushes to master with least-privilege permissions and reports findings as inline annotations. --- .github/workflows/zizmor.yml | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 00000000000..8b23730473c --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,36 @@ +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 DPNP repo + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@70fb788f84895a7701f5643d103d587e460b5c99 # v0.6.3 + with: + advanced-security: false + annotations: true + inputs: .github/ From 6c92bdedd4377eb476a1b240babf9a3d62087c40 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 12:05:31 +0200 Subject: [PATCH 2/7] ci: narrow workflow permissions to contents: read Replace top-level 'permissions: read-all' with the minimal 'contents: read' in check-onemath, conda-package and conda-package-cf; jobs needing more (actions: write to cancel prior runs, pull-requests: write to comment) already declare their own job-level permissions. --- .github/workflows/check-onemath.yaml | 3 ++- .github/workflows/conda-package-cf.yml | 3 ++- .github/workflows/conda-package.yml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/check-onemath.yaml b/.github/workflows/check-onemath.yaml index e5eb6375060..2aaf214f7a8 100644 --- a/.github/workflows/check-onemath.yaml +++ b/.github/workflows/check-onemath.yaml @@ -6,7 +6,8 @@ on: - master pull_request: -permissions: read-all +permissions: + contents: read env: environment-file: 'environments/environment.yml' diff --git a/.github/workflows/conda-package-cf.yml b/.github/workflows/conda-package-cf.yml index 7df0beafdf3..0fd80cb4375 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 concurrency: group: ${{ github.workflow }}-${{ github.ref }} diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index 9b2cbef75d3..f09144c3a2d 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: dpnp From 02c082c0c2be27bff9a9acb3ab27ceb86934fab3 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 12:07:14 +0200 Subject: [PATCH 3/7] ci: fix mismatched version comments on action hash pins Correct the version comments so they match the pinned commit SHAs (addresses zizmor's mismatched/missing version comment finding); the SHAs themselves are unchanged and already correct: - mshick/add-pr-comment: garbled 'v3.12.0.8.3.12.0' -> 'v3.12.0' in build-sphinx and conda-package. - oprypin/find-latest-tag: '1.1.3' -> 'v1.1.3' in cron-run-tests so the ref resolves. --- .github/workflows/build-sphinx.yml | 4 ++-- .github/workflows/conda-package.yml | 2 +- .github/workflows/cron-run-tests.yaml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build-sphinx.yml b/.github/workflows/build-sphinx.yml index b814ab00408..0ae37c5b659 100644 --- a/.github/workflows/build-sphinx.yml +++ b/.github/workflows/build-sphinx.yml @@ -238,7 +238,7 @@ jobs: if: env.GH_EVENT_PR_OPEN == 'true' && steps.check_fork.outputs.is_fork == 'false' 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-id: url_to_docs message: | @@ -282,7 +282,7 @@ jobs: git push tokened_docs gh-pages - name: Modify the comment with URL to official documentation - uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0.8.3.12.0 + uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0 with: message-id: url_to_docs find: | diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index f09144c3a2d..bd2acb78db9 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -851,7 +851,7 @@ jobs: - name: Post result to PR if: ${{ github.event.pull_request && !github.event.pull_request.head.repo.fork }} - uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0.8.3.12.0 + uses: mshick/add-pr-comment@ec328af66588ab8f77cdeb2c264f14aba45bbf59 # v3.12.0 with: message-id: array_api_results message: | diff --git a/.github/workflows/cron-run-tests.yaml b/.github/workflows/cron-run-tests.yaml index cd2be987c8c..a91192144d4 100644 --- a/.github/workflows/cron-run-tests.yaml +++ b/.github/workflows/cron-run-tests.yaml @@ -65,7 +65,7 @@ jobs: - name: Find the latest tag id: find_latest_tag - uses: oprypin/find-latest-tag@6957ac556fa6d349727ecabfcaaf9f8e5ee37124 # 1.1.3 + uses: oprypin/find-latest-tag@6957ac556fa6d349727ecabfcaaf9f8e5ee37124 # v1.1.3 with: repository: IntelPython/dpnp releases-only: false From aceddb2ad6e9d139beaf5dacb63916b084797fec Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 12:10:59 +0200 Subject: [PATCH 4/7] ci: add 7-day Dependabot cooldown to all update entries Set 'cooldown: default-days: 7' on the github-actions, pip, conda and pre-commit update entries so Dependabot waits a week after a release before opening an update PR (Dependabot's implicit default is 3 days). Addresses zizmor's dependabot-cooldown finding and reduces exposure to freshly published malicious or broken versions. --- .github/dependabot.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 233d0620ded..7af8cbab007 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -5,6 +5,8 @@ updates: schedule: interval: "weekly" day: "saturday" + cooldown: + default-days: 7 rebase-strategy: "disabled" labels: ["autoupdate"] groups: @@ -17,6 +19,8 @@ updates: schedule: interval: "weekly" day: "saturday" + cooldown: + default-days: 7 rebase-strategy: "disabled" labels: ["autoupdate"] groups: @@ -29,6 +33,8 @@ updates: schedule: interval: "weekly" day: "saturday" + cooldown: + default-days: 7 rebase-strategy: "disabled" labels: ["autoupdate"] groups: @@ -40,6 +46,8 @@ updates: schedule: interval: "weekly" day: "saturday" + cooldown: + default-days: 7 rebase-strategy: "disabled" labels: ["autoupdate"] groups: From f2b99b0ed3b8f7d6896bc3233775626cecd04d46 Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 12:17:43 +0200 Subject: [PATCH 5/7] ci: set persist-credentials: false on checkout steps Add 'persist-credentials: false' to the actions/checkout steps so the GITHUB_TOKEN is not persisted in .git/config for later steps (addresses zizmor's artipacked finding). The only credential-pushing steps use explicit tokens (a tokened remote in build-sphinx, the peter-evans/create-pull-request token input in bump-sycl-deps) rather than the persisted checkout credential, so they are unaffected. --- .github/workflows/build-sphinx.yml | 2 ++ .github/workflows/bump-sycl-deps.yml | 2 ++ .github/workflows/check-onemath.yaml | 4 ++++ .github/workflows/conda-build-test.yml | 2 ++ .github/workflows/conda-package.yml | 9 +++++++++ .github/workflows/generate_coverage.yaml | 1 + .github/workflows/os-llvm-sycl-build.yml | 2 ++ .github/workflows/pre-commit.yml | 1 + 8 files changed, 23 insertions(+) diff --git a/.github/workflows/build-sphinx.yml b/.github/workflows/build-sphinx.yml index 0ae37c5b659..bf2099bea0c 100644 --- a/.github/workflows/build-sphinx.yml +++ b/.github/workflows/build-sphinx.yml @@ -96,6 +96,7 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Install conda-merge tool @@ -265,6 +266,7 @@ jobs: steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Remove docs [PR closed] diff --git a/.github/workflows/bump-sycl-deps.yml b/.github/workflows/bump-sycl-deps.yml index 582caf70990..7eee31555bb 100644 --- a/.github/workflows/bump-sycl-deps.yml +++ b/.github/workflows/bump-sycl-deps.yml @@ -35,6 +35,8 @@ jobs: steps: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + with: + persist-credentials: false - name: Find latest intel/llvm driver release tag id: driver diff --git a/.github/workflows/check-onemath.yaml b/.github/workflows/check-onemath.yaml index 2aaf214f7a8..4bfdf6845a8 100644 --- a/.github/workflows/check-onemath.yaml +++ b/.github/workflows/check-onemath.yaml @@ -53,6 +53,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Install conda-merge tool @@ -111,6 +112,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Download artifact @@ -231,6 +233,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Download artifact @@ -242,6 +245,7 @@ jobs: - name: Checkout oneMKL repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false repository: 'oneapi-src/oneMKL' ref: 'develop' path: ${{ env.onemkl-source-dir }} diff --git a/.github/workflows/conda-build-test.yml b/.github/workflows/conda-build-test.yml index 79df2ab3219..8feaa00e058 100644 --- a/.github/workflows/conda-build-test.yml +++ b/.github/workflows/conda-build-test.yml @@ -64,6 +64,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Setup miniconda @@ -150,6 +151,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} path: ${{ env.dpnp-repo-path }} diff --git a/.github/workflows/conda-package.yml b/.github/workflows/conda-package.yml index bd2acb78db9..435964407a1 100644 --- a/.github/workflows/conda-package.yml +++ b/.github/workflows/conda-package.yml @@ -72,6 +72,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Setup miniconda @@ -172,6 +173,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} path: ${{ env.dpnp-repo-path }} @@ -326,6 +328,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} path: ${{ env.dpnp-repo-path }} @@ -443,6 +446,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} path: ${{ env.dpnp-repo-path }} @@ -637,6 +641,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} - name: Download artifact @@ -721,6 +726,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} path: ${{ env.dpnp-repo-path }} @@ -794,6 +800,7 @@ jobs: - name: Clone array API tests repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false repository: 'data-apis/array-api-tests' path: ${{ env.array-api-tests-path }} fetch-depth: ${{ env.fetch-depth }} @@ -877,6 +884,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: ${{ env.fetch-depth }} - name: Setup miniconda @@ -903,6 +911,7 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false repository: IntelPython/devops-tools fetch-depth: ${{ env.fetch-depth }} diff --git a/.github/workflows/generate_coverage.yaml b/.github/workflows/generate_coverage.yaml index bafc8ba8823..706e3085892 100644 --- a/.github/workflows/generate_coverage.yaml +++ b/.github/workflows/generate_coverage.yaml @@ -60,6 +60,7 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Install conda-merge tool diff --git a/.github/workflows/os-llvm-sycl-build.yml b/.github/workflows/os-llvm-sycl-build.yml index 8c8ecdf935f..bcaa2104725 100644 --- a/.github/workflows/os-llvm-sycl-build.yml +++ b/.github/workflows/os-llvm-sycl-build.yml @@ -106,11 +106,13 @@ jobs: - name: Checkout repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false fetch-depth: 0 - name: Checkout dpctl repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false repository: IntelPython/dpctl fetch-depth: 0 path: ${{ env.dpctl-repo-path }} diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index 7d8300ace67..bcd4afd8290 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -25,6 +25,7 @@ jobs: - name: Checkout DPNP repo uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: + persist-credentials: false # use commit hash to make "no-commit-to-branch" check passing ref: ${{ github.sha }} From ed52eaa321a7d34444673793ab5038fd3f27d02b Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 12:26:37 +0200 Subject: [PATCH 6/7] ci: pass reusable-workflow inputs via env to avoid template injection Move the inputs.channels-list, inputs.recipe-dir and env.python-conda-spec expansions in the conda-build/rebuild steps into step-level env vars and reference them as shell variables (addresses zizmor's high-severity template-injection findings). CHANNELS_LIST stays unquoted so it splits into separate -c CHANNEL args, with a scoped shellcheck disable; RECIPE_DIR is quoted. --- .github/workflows/conda-build-test.yml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/.github/workflows/conda-build-test.yml b/.github/workflows/conda-build-test.yml index 8feaa00e058..66fb986acbf 100644 --- a/.github/workflows/conda-build-test.yml +++ b/.github/workflows/conda-build-test.yml @@ -92,17 +92,33 @@ jobs: run: conda list - name: Store conda paths as envs + env: + CONDA_SUBDIR: ${{ inputs.conda-subdir }} run: | - echo "CONDA_BLD=$CONDA_PREFIX/conda-bld/${{ inputs.conda-subdir }}/" | tr "\\\\" '/' >> "$GITHUB_ENV" + echo "CONDA_BLD=$CONDA_PREFIX/conda-bld/$CONDA_SUBDIR/" | tr "\\\\" '/' >> "$GITHUB_ENV" - name: Build conda package id: build_conda_pkg continue-on-error: true - run: conda-build --no-test --python "${{ env.python-conda-spec }}" --numpy 2.0 ${{ inputs.channels-list }} ${{ inputs.recipe-dir }} + env: + PYTHON_CONDA_SPEC: ${{ env.python-conda-spec }} + CHANNELS_LIST: ${{ inputs.channels-list }} + RECIPE_DIR: ${{ inputs.recipe-dir }} + run: | + # CHANNELS_LIST must stay unquoted to split into separate CLI args + # shellcheck disable=SC2086 + conda-build --no-test --python "$PYTHON_CONDA_SPEC" --numpy 2.0 $CHANNELS_LIST "$RECIPE_DIR" - name: ReBuild conda package if: steps.build_conda_pkg.outcome == 'failure' - run: conda-build --no-test --python "${{ env.python-conda-spec }}" --numpy 2.0 ${{ inputs.channels-list }} ${{ inputs.recipe-dir }} + env: + PYTHON_CONDA_SPEC: ${{ env.python-conda-spec }} + CHANNELS_LIST: ${{ inputs.channels-list }} + RECIPE_DIR: ${{ inputs.recipe-dir }} + run: | + # CHANNELS_LIST must stay unquoted to split into separate CLI args + # shellcheck disable=SC2086 + conda-build --no-test --python "$PYTHON_CONDA_SPEC" --numpy 2.0 $CHANNELS_LIST "$RECIPE_DIR" - name: Upload artifact uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 From ba9d668b33085b895c46764cf3a1068300a173ce Mon Sep 17 00:00:00 2001 From: Anton Volkov Date: Tue, 1 Sep 2026 12:48:07 +0200 Subject: [PATCH 7/7] ci: gate zizmor job on medium+ severity findings Set min-severity: medium on the zizmor action so the job fails only on medium and high findings. The remaining low/informational template-injection notes come from internally-defined env/matrix values (no external input), so they are still surfaced as annotations but do not block CI. --- .github/workflows/zizmor.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml index 8b23730473c..7239d45711b 100644 --- a/.github/workflows/zizmor.yml +++ b/.github/workflows/zizmor.yml @@ -31,6 +31,9 @@ jobs: - 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/