From 45feb50e23825524351c228309f7be9aa0a6f70e Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Fri, 19 Jun 2026 15:26:45 +0200 Subject: [PATCH 1/3] ci: zizmor security hardening + audit + Dependabot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Harden the build workflows to pass zizmor (31 findings -> 0 actionable): - Pin every action to a commit SHA at its latest release (setup-python v6.2.0, upload-artifact v7.0.1, download-artifact v8.0.1, gh-release v3.0.0); checkout held at v6.0.3 to match the sibling repos (v7.0.0 is a fresh major — bump all together later). - persist-credentials: false on all checkouts. - Least-privilege top-level permissions: contents: read on build-python.yml (publish-release keeps contents: write). - template-injection: move inputs/env expansions out of run: blocks (incl. the Windows pwsh step -> $env:PYTHON_VERSION). - Drop secrets: inherit on the reusable-workflow call — the child declares no secrets and uses github.token directly. Add .github/workflows/zizmor.yml (official zizmor-action on push/PR -> code scanning, with fork-PR SARIF skip) and .github/dependabot.yml (github-actions, monthly, grouped, 7-day cooldown). Remaining: 1 informational superfluous-actions (softprops/action-gh-release). --- .github/workflows/build-python-version.yml | 38 +++++++++++++--------- .github/workflows/build-python.yml | 20 ++++++++---- .github/workflows/zizmor.yml | 28 ++++++++++++++++ 3 files changed, 65 insertions(+), 21 deletions(-) create mode 100644 .github/workflows/zizmor.yml diff --git a/.github/workflows/build-python-version.yml b/.github/workflows/build-python-version.yml index 0b30b43..f358c58 100644 --- a/.github/workflows/build-python-version.yml +++ b/.github/workflows/build-python-version.yml @@ -34,7 +34,9 @@ jobs: runs-on: macos-26 steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - name: Derive short Python version shell: bash @@ -42,7 +44,7 @@ jobs: echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -72,7 +74,7 @@ jobs: bash ./package-macos-for-dart.sh . "$PYTHON_VERSION" - name: Upload Darwin build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: python-darwin-${{ env.PYTHON_VERSION }} path: darwin/dist/python-*.tar.gz @@ -83,7 +85,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - name: Derive short Python version shell: bash @@ -91,7 +95,7 @@ jobs: echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -130,7 +134,7 @@ jobs: run: python3 -m unittest discover -s android/tests -t android/tests -v - name: Upload build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: python-android-${{ env.PYTHON_VERSION }} path: android/dist/python-android-*.tar.gz @@ -141,7 +145,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - name: Derive short Python version shell: bash @@ -149,7 +155,7 @@ jobs: echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -163,7 +169,7 @@ jobs: bash ./package-for-linux.sh aarch64 "" - name: Upload build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: python-linux-${{ env.PYTHON_VERSION }} path: linux/python-linux-dart-*.tar.gz @@ -173,16 +179,18 @@ jobs: name: Build Python for Windows runs-on: windows-2022 steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - name: Derive short Python version shell: pwsh run: | - $parts = "${{ env.PYTHON_VERSION }}".Split(".") + $parts = "$env:PYTHON_VERSION".Split(".") "PYTHON_VERSION_SHORT=$($parts[0]).$($parts[1])" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Python - uses: actions/setup-python@v6 + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -190,11 +198,11 @@ jobs: shell: pwsh run: | .\windows\package-for-dart.ps1 ` - -PythonVersion "${{ env.PYTHON_VERSION }}" ` - -PythonVersionShort "${{ env.PYTHON_VERSION_SHORT }}" + -PythonVersion "$env:PYTHON_VERSION" ` + -PythonVersionShort "$env:PYTHON_VERSION_SHORT" - name: Upload build artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: python-windows-${{ env.PYTHON_VERSION }} path: windows/python-windows-for-dart-*.zip diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index 40a43ac..ab74aba 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -20,6 +20,9 @@ concurrency: group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }} cancel-in-progress: true +permissions: + contents: read + jobs: setup: name: Read build matrix from manifest @@ -28,7 +31,9 @@ jobs: versions: ${{ steps.read.outputs.versions }} steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - name: Extract Python versions from manifest.json id: read # manifest.json is the single source of truth: it both selects which @@ -46,7 +51,6 @@ jobs: uses: ./.github/workflows/build-python-version.yml with: python_version: ${{ matrix.python_version }} - secrets: inherit publish-release: name: Publish Release Assets @@ -63,10 +67,12 @@ jobs: contents: write steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6 + with: + persist-credentials: false - name: Download all build artifacts - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: pattern: python-* path: release-artifacts @@ -75,10 +81,12 @@ jobs: - name: Add runtime manifest (with release date) to the release # Publish the same manifest.json that drove this build, with the release # date injected, so consumers can fetch a consistent version set by date. - run: jq '.release = "${{ inputs.release_date }}"' manifest.json > release-artifacts/manifest.json + env: + INPUTS_RELEASE_DATE: ${{ inputs.release_date }} + run: jq '.release = "${INPUTS_RELEASE_DATE}"' manifest.json > release-artifacts/manifest.json - name: Publish all artifacts to release - uses: softprops/action-gh-release@v3 + uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3 with: tag_name: ${{ inputs.release_date }} name: ${{ inputs.release_date }} diff --git a/.github/workflows/zizmor.yml b/.github/workflows/zizmor.yml new file mode 100644 index 0000000..e9ba32c --- /dev/null +++ b/.github/workflows/zizmor.yml @@ -0,0 +1,28 @@ +name: zizmor - GitHub Actions Security Analysis + +on: + push: + pull_request: + +permissions: {} + +jobs: + zizmor: + name: Run zizmor + runs-on: ubuntu-latest + permissions: + security-events: write + contents: read + steps: + - name: Checkout + uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 + with: + persist-credentials: false + + - name: Run zizmor + uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6 + with: + # Fork PRs get a read-only token (no security-events: write), so the + # SARIF upload would fail. Skip it for forks — they still get inline + # annotations; pushes and same-repo PRs upload to code scanning. + advanced-security: ${{ github.event.pull_request.head.repo.fork != true }} From 0ed328369fae8de6e0a9091d5badb87d6b2ef3ce Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Wed, 24 Jun 2026 16:46:25 +0200 Subject: [PATCH 2/3] fix(ci): update mismatched action SHA comments MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - actions/setup-python: v6.2.0 → v6.3.0 (ece7cb06) - softprops/action-gh-release: v3.0.0 → v3.0.1 (718ea10b) Both SHAs were behind their version comments, triggering zizmor's mismatched-hash-comment audit in GitHub Code Scanning. --- .github/workflows/build-python-version.yml | 8 ++++---- .github/workflows/build-python.yml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/build-python-version.yml b/.github/workflows/build-python-version.yml index f358c58..5af4562 100644 --- a/.github/workflows/build-python-version.yml +++ b/.github/workflows/build-python-version.yml @@ -44,7 +44,7 @@ jobs: echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - name: Setup Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -95,7 +95,7 @@ jobs: echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - name: Setup Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -155,7 +155,7 @@ jobs: echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV" - name: Setup Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} @@ -190,7 +190,7 @@ jobs: "PYTHON_VERSION_SHORT=$($parts[0]).$($parts[1])" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append - name: Setup Python - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 + uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0 with: python-version: ${{ env.PYTHON_VERSION_SHORT }} diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index ab74aba..d8682ad 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -86,7 +86,7 @@ jobs: run: jq '.release = "${INPUTS_RELEASE_DATE}"' manifest.json > release-artifacts/manifest.json - name: Publish all artifacts to release - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3 + uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1 with: tag_name: ${{ inputs.release_date }} name: ${{ inputs.release_date }} From 064ed44e6ac23d134b5fb0afd5f4c948fcca6cfa Mon Sep 17 00:00:00 2001 From: ndonkoHenri Date: Wed, 24 Jun 2026 16:50:40 +0200 Subject: [PATCH 3/3] fix(ci): use jq --arg to correctly inject release date into manifest --- .github/workflows/build-python.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/build-python.yml b/.github/workflows/build-python.yml index d8682ad..b05d800 100644 --- a/.github/workflows/build-python.yml +++ b/.github/workflows/build-python.yml @@ -83,7 +83,7 @@ jobs: # date injected, so consumers can fetch a consistent version set by date. env: INPUTS_RELEASE_DATE: ${{ inputs.release_date }} - run: jq '.release = "${INPUTS_RELEASE_DATE}"' manifest.json > release-artifacts/manifest.json + run: jq --arg date "$INPUTS_RELEASE_DATE" '.release = $date' manifest.json > release-artifacts/manifest.json - name: Publish all artifacts to release uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1