Skip to content

Commit ed867e7

Browse files
authored
ci: zizmor security checks (#23)
* ci: zizmor security hardening + audit + Dependabot 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). * fix(ci): update mismatched action SHA comments - 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. * fix(ci): use jq --arg to correctly inject release date into manifest
1 parent 5cc961a commit ed867e7

3 files changed

Lines changed: 65 additions & 21 deletions

File tree

.github/workflows/build-python-version.yml

Lines changed: 23 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,17 @@ jobs:
3434
runs-on: macos-26
3535
steps:
3636
- name: Checkout
37-
uses: actions/checkout@v6
37+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
38+
with:
39+
persist-credentials: false
3840

3941
- name: Derive short Python version
4042
shell: bash
4143
run: |
4244
echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV"
4345
4446
- name: Setup Python
45-
uses: actions/setup-python@v6
47+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
4648
with:
4749
python-version: ${{ env.PYTHON_VERSION_SHORT }}
4850

@@ -72,7 +74,7 @@ jobs:
7274
bash ./package-macos-for-dart.sh . "$PYTHON_VERSION"
7375
7476
- name: Upload Darwin build artifacts
75-
uses: actions/upload-artifact@v7
77+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
7678
with:
7779
name: python-darwin-${{ env.PYTHON_VERSION }}
7880
path: darwin/dist/python-*.tar.gz
@@ -83,15 +85,17 @@ jobs:
8385
runs-on: ubuntu-latest
8486
steps:
8587
- name: Checkout
86-
uses: actions/checkout@v6
88+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
89+
with:
90+
persist-credentials: false
8791

8892
- name: Derive short Python version
8993
shell: bash
9094
run: |
9195
echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV"
9296
9397
- name: Setup Python
94-
uses: actions/setup-python@v6
98+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
9599
with:
96100
python-version: ${{ env.PYTHON_VERSION_SHORT }}
97101

@@ -130,7 +134,7 @@ jobs:
130134
run: python3 -m unittest discover -s android/tests -t android/tests -v
131135

132136
- name: Upload build artifacts
133-
uses: actions/upload-artifact@v7
137+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
134138
with:
135139
name: python-android-${{ env.PYTHON_VERSION }}
136140
path: android/dist/python-android-*.tar.gz
@@ -141,15 +145,17 @@ jobs:
141145
runs-on: ubuntu-latest
142146
steps:
143147
- name: Checkout
144-
uses: actions/checkout@v6
148+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
149+
with:
150+
persist-credentials: false
145151

146152
- name: Derive short Python version
147153
shell: bash
148154
run: |
149155
echo "PYTHON_VERSION_SHORT=$(echo "$PYTHON_VERSION" | cut -d. -f1,2)" >> "$GITHUB_ENV"
150156
151157
- name: Setup Python
152-
uses: actions/setup-python@v6
158+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
153159
with:
154160
python-version: ${{ env.PYTHON_VERSION_SHORT }}
155161

@@ -163,7 +169,7 @@ jobs:
163169
bash ./package-for-linux.sh aarch64 ""
164170
165171
- name: Upload build artifacts
166-
uses: actions/upload-artifact@v7
172+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
167173
with:
168174
name: python-linux-${{ env.PYTHON_VERSION }}
169175
path: linux/python-linux-dart-*.tar.gz
@@ -173,28 +179,30 @@ jobs:
173179
name: Build Python for Windows
174180
runs-on: windows-2022
175181
steps:
176-
- uses: actions/checkout@v6
182+
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
183+
with:
184+
persist-credentials: false
177185

178186
- name: Derive short Python version
179187
shell: pwsh
180188
run: |
181-
$parts = "${{ env.PYTHON_VERSION }}".Split(".")
189+
$parts = "$env:PYTHON_VERSION".Split(".")
182190
"PYTHON_VERSION_SHORT=$($parts[0]).$($parts[1])" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
183191
184192
- name: Setup Python
185-
uses: actions/setup-python@v6
193+
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
186194
with:
187195
python-version: ${{ env.PYTHON_VERSION_SHORT }}
188196

189197
- name: Build CPython from sources and package for Dart
190198
shell: pwsh
191199
run: |
192200
.\windows\package-for-dart.ps1 `
193-
-PythonVersion "${{ env.PYTHON_VERSION }}" `
194-
-PythonVersionShort "${{ env.PYTHON_VERSION_SHORT }}"
201+
-PythonVersion "$env:PYTHON_VERSION" `
202+
-PythonVersionShort "$env:PYTHON_VERSION_SHORT"
195203
196204
- name: Upload build artifacts
197-
uses: actions/upload-artifact@v7
205+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
198206
with:
199207
name: python-windows-${{ env.PYTHON_VERSION }}
200208
path: windows/python-windows-for-dart-*.zip

.github/workflows/build-python.yml

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ concurrency:
2020
group: ${{ github.workflow }}-${{ github.head_ref || github.ref_name }}
2121
cancel-in-progress: true
2222

23+
permissions:
24+
contents: read
25+
2326
jobs:
2427
setup:
2528
name: Read build matrix from manifest
@@ -28,7 +31,9 @@ jobs:
2831
versions: ${{ steps.read.outputs.versions }}
2932
steps:
3033
- name: Checkout repository
31-
uses: actions/checkout@v6
34+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
35+
with:
36+
persist-credentials: false
3237
- name: Extract Python versions from manifest.json
3338
id: read
3439
# manifest.json is the single source of truth: it both selects which
@@ -46,7 +51,6 @@ jobs:
4651
uses: ./.github/workflows/build-python-version.yml
4752
with:
4853
python_version: ${{ matrix.python_version }}
49-
secrets: inherit
5054

5155
publish-release:
5256
name: Publish Release Assets
@@ -63,10 +67,12 @@ jobs:
6367
contents: write
6468
steps:
6569
- name: Checkout repository
66-
uses: actions/checkout@v6
70+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6
71+
with:
72+
persist-credentials: false
6773

6874
- name: Download all build artifacts
69-
uses: actions/download-artifact@v8
75+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
7076
with:
7177
pattern: python-*
7278
path: release-artifacts
@@ -75,10 +81,12 @@ jobs:
7581
- name: Add runtime manifest (with release date) to the release
7682
# Publish the same manifest.json that drove this build, with the release
7783
# date injected, so consumers can fetch a consistent version set by date.
78-
run: jq '.release = "${{ inputs.release_date }}"' manifest.json > release-artifacts/manifest.json
84+
env:
85+
INPUTS_RELEASE_DATE: ${{ inputs.release_date }}
86+
run: jq --arg date "$INPUTS_RELEASE_DATE" '.release = $date' manifest.json > release-artifacts/manifest.json
7987

8088
- name: Publish all artifacts to release
81-
uses: softprops/action-gh-release@v3
89+
uses: softprops/action-gh-release@718ea10b132b3b2eba29c1007bb80653f286566b # v3.0.1
8290
with:
8391
tag_name: ${{ inputs.release_date }}
8492
name: ${{ inputs.release_date }}

.github/workflows/zizmor.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: zizmor - GitHub Actions Security Analysis
2+
3+
on:
4+
push:
5+
pull_request:
6+
7+
permissions: {}
8+
9+
jobs:
10+
zizmor:
11+
name: Run zizmor
12+
runs-on: ubuntu-latest
13+
permissions:
14+
security-events: write
15+
contents: read
16+
steps:
17+
- name: Checkout
18+
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
19+
with:
20+
persist-credentials: false
21+
22+
- name: Run zizmor
23+
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
24+
with:
25+
# Fork PRs get a read-only token (no security-events: write), so the
26+
# SARIF upload would fail. Skip it for forks — they still get inline
27+
# annotations; pushes and same-repo PRs upload to code scanning.
28+
advanced-security: ${{ github.event.pull_request.head.repo.fork != true }}

0 commit comments

Comments
 (0)