Skip to content

Commit 6503865

Browse files
authored
Harden Samples CI workflow for zizmor and add workflow linting (#95)
Follow-up to #80, which added the zizmor pre-commit hook but excluded run-samples.yml (the repo's only substantive workflow), making the hook effectively a no-op. This fixes the underlying findings and removes the exclude so zizmor actually lints the workflow, locally and in CI. run-samples.yml: - Add top-level and grant each job only - Pin all actions to full commit SHAs with version comments (unpinned-uses) - Set on both checkout steps (artipacked) - Route github.event.inputs.run_mode, matrix.shard/splits and runner.temp through step-level env instead of inline interpolation (template-injection) - Quote and in the MSSQL step (shellcheck) .pre-commit-config.yaml: - Remove the run-samples.yml exclude on the zizmor hook lint_workflows.yml: - Add a dedicated workflow-linting job (actionlint + zizmor) mirroring localstack-pro, for CI parity and shellcheck coverage on run: blocks
1 parent b97d393 commit 6503865

3 files changed

Lines changed: 71 additions & 13 deletions

File tree

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
name: Lint GitHub Actions workflows
2+
3+
# Lints the repo's own GitHub Actions workflows:
4+
# - actionlint: workflow syntax, expression and runner-label checks, plus shellcheck on run: blocks
5+
# - zizmor: workflow security (also enforced locally via the pre-commit hook)
6+
7+
on:
8+
push:
9+
branches:
10+
- main
11+
paths:
12+
- '.github/workflows/**'
13+
pull_request:
14+
paths:
15+
- '.github/workflows/**'
16+
17+
permissions: {}
18+
19+
jobs:
20+
lint_workflows:
21+
name: "Run linters"
22+
runs-on: ubuntu-latest
23+
permissions:
24+
contents: read
25+
actions: read
26+
27+
steps:
28+
- name: Check out repo
29+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
30+
with:
31+
persist-credentials: false
32+
33+
- name: Run actionlint
34+
uses: raven-actions/actionlint@205b530c5d9fa8f44ae9ed59f341a0db994aa6f8 # v2.1.2
35+
36+
- name: Run zizmor
37+
uses: zizmorcore/zizmor-action@5f14fd08f7cf1cb1609c1e344975f152c7ee938d # v0.5.6
38+
with:
39+
# Don't integrate with GitHub Advanced Security
40+
advanced-security: false

.github/workflows/run-samples.yml

Lines changed: 31 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -25,26 +25,35 @@ on:
2525
env:
2626
DEFAULT_RUN_MODE: changed
2727

28+
# Least-privilege default: no permissions unless a job explicitly opts in.
29+
permissions: {}
30+
2831
jobs:
2932
# Lightweight job that builds the dynamic test matrix for the main test jobs
3033
setup:
3134
name: "Build Test Matrix"
3235
runs-on: ubuntu-latest
36+
permissions:
37+
contents: read
3338
outputs:
3439
matrix: ${{ steps.build-matrix.outputs.matrix }}
3540
has_tests: ${{ steps.build-matrix.outputs.has_tests }}
3641
steps:
3742
- name: Checkout repo
38-
uses: actions/checkout@v4
43+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
3944
with:
4045
fetch-depth: 0 # Full history needed for git diff in "changed" mode
46+
persist-credentials: false
4147

4248
- name: Build dynamic matrix
4349
id: build-matrix
50+
env:
51+
# Untrusted dispatch input routed via env, not interpolated into the shell (template-injection)
52+
RUN_MODE_INPUT: ${{ github.event.inputs.run_mode }}
4453
run: |
4554
# Pick run mode: manual dispatch uses the dropdown, PRs use the env default
4655
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
47-
RUN_MODE="${{ github.event.inputs.run_mode }}"
56+
RUN_MODE="${RUN_MODE_INPUT}"
4857
else
4958
RUN_MODE="${{ env.DEFAULT_RUN_MODE }}"
5059
fi
@@ -72,29 +81,36 @@ jobs:
7281
matrix: ${{ fromJSON(needs.setup.outputs.matrix) }}
7382
runs-on: ubuntu-22.04
7483

84+
permissions:
85+
contents: read
86+
7587
env:
7688
IMAGE_NAME: localstack/localstack-azure-alpha
7789
DEFAULT_TAG: latest
7890

7991
steps:
8092
- name: Checkout repo
81-
uses: actions/checkout@v4
93+
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
94+
with:
95+
persist-credentials: false
8296

8397
- name: Set up environment
84-
run: echo "AZURE_CONFIG_DIR=${{ runner.temp }}/azure-cli" >> $GITHUB_ENV
98+
env:
99+
RUNNER_TEMP_DIR: ${{ runner.temp }}
100+
run: echo "AZURE_CONFIG_DIR=${RUNNER_TEMP_DIR}/azure-cli" >> "$GITHUB_ENV"
85101

86102
- name: Set up Python
87-
uses: actions/setup-python@v5
103+
uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
88104
with:
89105
python-version: '3.12'
90106
cache: 'pip'
91107

92108
- name: Set up .NET
93-
uses: actions/setup-dotnet@v4
109+
uses: actions/setup-dotnet@67a3573c9a986a3f9c594539f4ab511d57bb3ce9 # v4.3.1
94110
with:
95111
dotnet-version: '10.0'
96112

97-
- uses: actions/setup-java@v5
113+
- uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
98114
with:
99115
distribution: 'temurin'
100116
java-version: '25'
@@ -110,7 +126,7 @@ jobs:
110126
find . -name "*.sh" -exec chmod +x {} +
111127
112128
- name: Install Terraform
113-
uses: hashicorp/setup-terraform@v3
129+
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3.1.2
114130
with:
115131
terraform_version: "1.5.0"
116132
terraform_wrapper: false
@@ -123,7 +139,7 @@ jobs:
123139
- name: Login to Docker Hub
124140
# Mandatory login to Docker Hub to benefit from higher rate limits for authenticated pulls.
125141
# This prevents '429 Too Many Requests' errors during the pull of large emulator images.
126-
uses: docker/login-action@v3
142+
uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0
127143
with:
128144
username: ${{ secrets.DOCKERHUB_PULL_USERNAME }}
129145
password: ${{ secrets.DOCKERHUB_PULL_TOKEN }}
@@ -178,16 +194,19 @@ jobs:
178194
run: |
179195
sudo rm -f /etc/apt/sources.list.d/microsoft-prod.list
180196
curl https://packages.microsoft.com/keys/microsoft.asc | sudo tee /etc/apt/trusted.gpg.d/microsoft.asc
181-
curl https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list | sudo tee /etc/apt/sources.list.d/mssql-release.list
197+
curl "https://packages.microsoft.com/config/ubuntu/$(lsb_release -rs)/prod.list" | sudo tee /etc/apt/sources.list.d/mssql-release.list
182198
sudo apt-get update
183199
sudo ACCEPT_EULA=Y apt-get install -y msodbcsql18 mssql-tools18
184-
echo "/opt/mssql-tools18/bin" >> $GITHUB_PATH
200+
echo "/opt/mssql-tools18/bin" >> "$GITHUB_PATH"
185201
186202
- name: "Run: ${{ matrix.name }}"
187203
# Each job runs exactly one test. SPLITS equals the total test count, and SHARD
188204
# is the 1-based index of this specific test, so run-samples.sh executes only it.
189-
run: make test SHARD=${{ matrix.shard }} SPLITS=${{ matrix.splits }}
205+
run: make test SHARD="${SHARD}" SPLITS="${SPLITS}"
190206
env:
207+
# Dynamic matrix values routed via env, not interpolated into the shell (template-injection)
208+
SHARD: ${{ matrix.shard }}
209+
SPLITS: ${{ matrix.splits }}
191210
LOCALSTACK_AUTH_TOKEN: ${{ secrets.TEST_LOCALSTACK_AUTH_TOKEN }}
192211

193212
- name: Get LocalStack Logs

.pre-commit-config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ repos:
33
rev: v1.25.2
44
hooks:
55
- id: zizmor
6-
exclude: ^\.github/workflows/run-samples\.yml$
76

87
- repo: https://github.com/gitleaks/gitleaks
98
rev: v8.30.1

0 commit comments

Comments
 (0)