Skip to content

Commit 9e44a7a

Browse files
authored
ci: add zizmor linter to better scrutinize github actions (#830)
* ci: add zizmor linter to better scrutinize github actions * chore: ignore CVE-2025-50182 for a certain amount of time * chore: try and ignore trivy finding * chore: ignore correct id * chore: ignore both vulnerabilities in urllib3 * chore: fix zizmor findings * chore: fix more issues * chore: fix more issues * chore: prevent attacker-controllable input * chore: more fixes * chore: fix python error * chore: more fixing * chore: removing 'secrets: inherit'
1 parent e0d51f9 commit 9e44a7a

File tree

13 files changed

+95
-54
lines changed

13 files changed

+95
-54
lines changed

.github/actions/container-size-diff/action.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,10 @@ outputs:
1818
runs:
1919
using: "composite"
2020
steps:
21-
- run: echo "$GITHUB_ACTION_PATH" >> "$GITHUB_PATH"
22-
shell: bash
23-
env:
24-
GITHUB_ACTION_PATH: ${{ github.action_path }}
2521
- run: |
2622
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
2723
echo "markdown<<${EOF}" >> "${GITHUB_OUTPUT}"
28-
echo "$(container-size-diff.sh ${INPUT_FROM_CONTAINER} ${INPUT_TO_CONTAINER})" >> "${GITHUB_OUTPUT}"
24+
echo "$(${GITHUB_ACTION_PATH}/container-size-diff.sh ${INPUT_FROM_CONTAINER} ${INPUT_TO_CONTAINER})" >> "${GITHUB_OUTPUT}"
2925
echo "${EOF}" >> "${GITHUB_OUTPUT}"
3026
id: size-diff
3127
shell: bash

.github/actions/container-size-diff/container-size-diff.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
#!/usr/bin/env bash
22

3+
set -Eeuo pipefail
4+
35
FROM_CONTAINER=${1:?}
46
TO_CONTAINER=${2:?}
57

.github/actions/update-apt-packages/action.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,12 @@ outputs:
1515
runs:
1616
using: "composite"
1717
steps:
18-
- run: echo "$GITHUB_ACTION_PATH" >> "$GITHUB_PATH"
19-
shell: bash
20-
env:
21-
GITHUB_ACTION_PATH: ${{ github.action_path }}
2218
- run: |
2319
apt-get update
2420
apt-get install --no-install-recommends -y jq
2521
shell: bash
2622
- run: |
27-
update-apt-packages.sh ${INPUT_FILE}
23+
${GITHUB_ACTION_PATH}/update-apt-packages.sh ${INPUT_FILE}
2824
echo "updated-dependencies=$(cat updated-packages.json)" >> "${GITHUB_OUTPUT}"
2925
rm updated-packages.json
3026
id: update-extensions

.github/actions/update-vscode-extensions/action.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ outputs:
1818
runs:
1919
using: "composite"
2020
steps:
21-
- run: echo "$GITHUB_ACTION_PATH" >> "$GITHUB_PATH"
22-
shell: bash
23-
env:
24-
GITHUB_ACTION_PATH: ${{ github.action_path }}
2521
- run: |
2622
sudo apt-get update
2723
sudo apt-get install --no-install-recommends -y jq
@@ -30,7 +26,7 @@ runs:
3026
- run: |
3127
EOF=$(dd if=/dev/urandom bs=15 count=1 status=none | base64)
3228
echo "markdown-summary<<${EOF}" >> "${GITHUB_OUTPUT}"
33-
echo "$(update-vscode-extensions.sh ${INPUT_FILE})" >> "${GITHUB_OUTPUT}"
29+
echo "$(${GITHUB_ACTION_PATH}/update-vscode-extensions.sh ${INPUT_FILE})" >> "${GITHUB_OUTPUT}"
3430
echo "${EOF}" >> "${GITHUB_OUTPUT}"
3531
3632
echo "updated-dependencies=$(cat updated-extensions.json)" >> "${GITHUB_OUTPUT}"

.github/linters/.trivyignore.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
misconfigurations:
3+
- id: AVD-DS-0002
4+
statement: We allow root access in our container that we use for development purposes (https://avd.aquasec.com/misconfig/dockerfile/general/avd-ds-0002/)
5+
vulnerabilities:
6+
- id: CVE-2025-50181
7+
paths:
8+
- ".devcontainer/cpp/requirements.txt"
9+
expired_at: 2025-10-01
10+
statement: This vulnerable dependency comes in via the Conan package, work is in-progress on supporting a non-vulnerable version (https://github.com/conan-io/conan/issues/13948)
11+
- id: CVE-2025-50182
12+
paths:
13+
- ".devcontainer/cpp/requirements.txt"
14+
expired_at: 2025-10-01
15+
statement: This vulnerable dependency comes in via the Conan package, work is in-progress on supporting a non-vulnerable version (https://github.com/conan-io/conan/issues/13948)

.github/workflows/linting-formatting.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ jobs:
2828
with:
2929
fetch-depth: 0
3030
persist-credentials: false
31+
- uses: zizmorcore/zizmor-action@f52a838cfabf134edcbaa7c8b3677dde20045018 # v0.1.1
3132
# flavors/dotnet is the smallest flavor of MegaLinter that contains the linters
3233
# we are interested in.
3334
- uses: oxsecurity/megalinter/flavors/dotnet@e08c2b05e3dbc40af4c23f41172ef1e068a7d651 # v8.8.0

.github/workflows/release-build.yml

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,52 +26,67 @@ jobs:
2626
id-token: write
2727
packages: write
2828
pull-requests: write
29+
with:
30+
# Disable the cache for release builds
31+
enable-cache: false
2932
apply-release-notes-template:
3033
runs-on: ubuntu-latest
3134
steps:
3235
- uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1
3336
with:
3437
egress-policy: audit
38+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
39+
with:
40+
persist-credentials: false
3541
- name: Amend release description
36-
env:
37-
GITHUB_TOKEN: ${{ github.token }}
3842
run: |
39-
CURRENT_NOTES=$(gh release view ${{ github.ref_name }} --json body -q '.body')
43+
set -Eeuo pipefail
44+
CURRENT_NOTES=$(gh release view "${REF_NAME}" --json body -q '.body')
4045
HEADER=$(echo "$CURRENT_NOTES" | awk '/^## / {print; exit}')
4146
TEMPLATE=$(cat "$GITHUB_WORKSPACE/.github/RELEASE_TEMPLATE.md")
4247
BODY=$(echo "$CURRENT_NOTES" | sed "0,/^## /d")
43-
gh release edit ${{ github.ref_name }} --notes "${HEADER}${TEMPLATE}${BODY}"
48+
gh release edit "${REF_NAME}" --notes "${HEADER}${TEMPLATE}${BODY}"
49+
env:
50+
GITHUB_TOKEN: ${{ github.token }}
51+
REF_NAME: ${{ github.ref_name }}
4452
update-release-notes:
4553
strategy:
4654
matrix:
4755
flavor: [cpp, rust]
4856
runs-on: ubuntu-latest
49-
needs: build-push-test
57+
needs: [build-push-test, apply-release-notes-template]
5058
env:
59+
CONTAINER_FLAVOR: ${{ matrix.flavor }}
60+
REF_NAME: ${{ github.ref_name }}
5161
REGISTRY: ghcr.io
5262
steps:
53-
- uses: step-security/harden-runner@0634a2670c59f64b4a01f0f96f84700a4088b9f0 # v2.12.0
63+
- uses: step-security/harden-runner@002fdce3c6a235733a90a27c80493a3241e56863 # v2.12.1
5464
with:
5565
egress-policy: audit
5666
- name: Inspect manifest and extract digest
5767
id: inspect-manifest
5868
run: |
5969
set -Eeuo pipefail
60-
output=$(docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}:${{ github.ref_name }} --format '{{json .}}')
70+
output=$(docker buildx imagetools inspect "${REGISTRY}/${{ github.repository }}-${CONTAINER_FLAVOR}:${REF_NAME}" --format '{{json .}}')
6171
echo "digest=$(echo "$output" | jq -r '.manifest.digest // .manifests[0].digest')" >> "$GITHUB_OUTPUT"
6272
- name: Upload provenance to release
73+
run: |
74+
set -Eeuo pipefail
75+
FORMATTED_DIGEST=${DIGEST//:/_}
76+
gh attestation verify --repo ${{ github.repository }} "oci://${REGISTRY}/${{ github.repository }}-${CONTAINER_FLAVOR}@${DIGEST}" --format json --jq '.[] | .attestation.bundle.dsseEnvelope | select(.payloadType == "application/vnd.in-toto+json").payload' | base64 -d | jq . > "${REPOSITORY_OWNER}-${REPOSITORY_NAME}-${CONTAINER_FLAVOR}_${FORMATTED_DIGEST}.intoto.jsonl"
77+
gh release upload "${REF_NAME}" ./*.intoto.jsonl
6378
env:
79+
DIGEST: ${{ steps.inspect-manifest.outputs.digest }}
6480
GH_TOKEN: ${{ github.token }}
65-
run: |
66-
RAW_SHA=${{ steps.inspect-manifest.outputs.digest }}
67-
FORMATTED_SHA=${RAW_SHA//:/_}
68-
gh attestation verify --repo ${{ github.repository }} oci://${{ env.REGISTRY }}/${{ github.repository }}-${{ matrix.flavor }}@${{ steps.inspect-manifest.outputs.digest }} --format json --jq '.[] | .attestation.bundle.dsseEnvelope | select(.payloadType == "application/vnd.in-toto+json").payload' | base64 -d | jq . > "${{ github.repository_owner }}-${{ github.event.repository.name }}-${{ matrix.flavor }}_${FORMATTED_SHA}.intoto.jsonl"
69-
gh release upload ${{ github.ref_name }} ./*.intoto.jsonl
81+
REPOSITORY_OWNER: ${{ github.repository_owner }}
82+
REPOSITORY_NAME: ${{ github.event.repository.name }}
7083
- name: Update package details in release
84+
run: |
85+
set -Eeuo pipefail
86+
UPDATED_NOTES=$(gh release view "${REF_NAME}" --json body -q '.body')
87+
UPDATED_NOTES=${UPDATED_NOTES//"{{ amp-devcontainer-${CONTAINER_FLAVOR}-version }}"/"${REF_NAME}"}
88+
UPDATED_NOTES=${UPDATED_NOTES//"{{ amp-devcontainer-${CONTAINER_FLAVOR}-sha }}"/"${DIGEST}"}
89+
gh release edit "${REF_NAME}" --notes "${UPDATED_NOTES}"
7190
env:
91+
DIGEST: ${{ steps.inspect-manifest.outputs.digest }}
7292
GH_TOKEN: ${{ github.token }}
73-
run: |
74-
UPDATED_NOTES=$(gh release view ${{ github.ref_name }} --json body -q '.body')
75-
UPDATED_NOTES=${UPDATED_NOTES//'{{ amp-devcontainer-${{ matrix.flavor }}-version }}'/'${{ github.ref_name }}'}
76-
UPDATED_NOTES=${UPDATED_NOTES//'{{ amp-devcontainer-${{ matrix.flavor }}-sha }}'/'${{ steps.inspect-manifest.outputs.digest }}'}
77-
gh release edit ${{ github.ref_name }} --notes "${UPDATED_NOTES}"

.github/workflows/wc-acceptance-test.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ jobs:
3939
gh secret set -a codespaces IMAGE_VERSION --body "edge"
4040
fi
4141
42-
echo CODESPACE_NAME="$(gh codespace create -R "${{ github.repository }}" -b "$HEAD_REF" -m basicLinux32gb --devcontainer-path ".devcontainer/${{ inputs.flavor }}-test/devcontainer.json" --idle-timeout 10m --retention-period 1h)" >> "$GITHUB_ENV"
42+
echo CODESPACE_NAME="$(gh codespace create -R "${{ github.repository }}" -b "$HEAD_REF" -m basicLinux32gb --devcontainer-path ".devcontainer/${CONTAINER_FLAVOR}-test/devcontainer.json" --idle-timeout 10m --retention-period 1h)" >> "$GITHUB_ENV"
4343
env:
44+
CONTAINER_FLAVOR: ${{ inputs.flavor }}
4445
GH_TOKEN: ${{ secrets.TEST_GITHUB_TOKEN }}
4546
HEAD_REF: ${{ github.head_ref }}
4647
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
@@ -56,7 +57,7 @@ jobs:
5657
SECONDS_ELAPSED=0
5758
5859
while true; do
59-
STATE=$(gh codespace list --json name,state --jq ".[] | select(.name == \"$CODESPACE_NAME\") | .state")
60+
STATE=$(gh codespace list --json name,state --jq ".[] | select(.name == \"${CODESPACE_NAME}\") | .state")
6061
echo "Current state: $STATE"
6162
if [ "$STATE" == "Available" ]; then
6263
echo "Codespace is active!"
@@ -71,8 +72,9 @@ jobs:
7172
done
7273
env:
7374
GH_TOKEN: ${{ secrets.TEST_GITHUB_TOKEN }}
74-
- run: cd test/${{ inputs.flavor }}/features && npm test
75+
- run: cd "test/${CONTAINER_FLAVOR}/features" && npm test
7576
env:
77+
CONTAINER_FLAVOR: ${{ inputs.flavor }}
7678
GITHUB_USER: ${{ secrets.TEST_GITHUB_USER }}
7779
GITHUB_PASSWORD: ${{ secrets.TEST_GITHUB_PASSWORD }}
7880
GITHUB_TOTP_SECRET: ${{ secrets.TEST_GITHUB_TOTP_SECRET }}
@@ -85,7 +87,7 @@ jobs:
8587
retention-days: 10
8688
- run: |
8789
set -Eeuo pipefail
88-
gh codespace delete --force --codespace "$CODESPACE_NAME"
90+
gh codespace delete --force --codespace "${CODESPACE_NAME}"
8991
gh secret set -a codespaces IMAGE_VERSION --body "latest"
9092
if: always()
9193
env:

.github/workflows/wc-build-push-test.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@ name: Build, Push & Test
33

44
on:
55
workflow_call:
6+
inputs:
7+
enable-cache:
8+
required: false
9+
type: boolean
10+
default: true
611

712
permissions:
813
contents: read
@@ -13,7 +18,6 @@ jobs:
1318
matrix:
1419
flavor: [cpp, rust]
1520
uses: ./.github/workflows/wc-build-push.yml
16-
secrets: inherit
1721
permissions:
1822
actions: read
1923
attestations: write
@@ -23,6 +27,7 @@ jobs:
2327
pull-requests: write
2428
with:
2529
flavor: ${{ matrix.flavor }}
30+
enable-cache: ${{ inputs.enable-cache }}
2631

2732
dependency-review:
2833
runs-on: ubuntu-latest

.github/workflows/wc-build-push.yml

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@ on:
77
flavor:
88
required: true
99
type: string
10+
enable-cache:
11+
required: false
12+
type: boolean
13+
default: true
1014

1115
permissions:
1216
contents: read
1317

1418
env:
19+
CONTAINER_FLAVOR: ${{ inputs.flavor }}
1520
REGISTRY: ghcr.io
1621

1722
jobs:
@@ -43,7 +48,7 @@ jobs:
4348
images: ${{ env.REGISTRY }}/${{ github.repository }}-${{ inputs.flavor }}
4449
# Generate image LABEL for devcontainer.metadata
4550
# the sed expression is a workaround for quotes being eaten in arrays (e.g. ["x", "y", "z"] -> ["x",y,"z"])
46-
- run: echo "metadata=$(jq -cj '[.]' .devcontainer/${{ inputs.flavor }}/devcontainer-metadata-vscode.json | sed 's/,"/, "/g')" >> "$GITHUB_OUTPUT"
51+
- run: echo "metadata=$(jq -cj '[.]' ".devcontainer/${CONTAINER_FLAVOR}/devcontainer-metadata-vscode.json" | sed 's/,"/, "/g')" >> "$GITHUB_OUTPUT"
4752
id: devcontainer-metadata
4853
- run: echo "git-commit-epoch=$(git log -1 --pretty=%ct)" >> "$GITHUB_OUTPUT"
4954
id: devcontainer-epoch
@@ -63,13 +68,15 @@ jobs:
6368
annotations: ${{ steps.metadata.outputs.annotations }}
6469
sbom: true
6570
outputs: type=image,push-by-digest=true,name-canonical=true
66-
cache-to: type=gha,mode=max,scope=${{ github.repository }}-${{ inputs.flavor }}-${{ matrix.runner }}
67-
cache-from: type=gha,scope=${{ github.repository }}-${{ inputs.flavor }}-${{ matrix.runner }}
71+
cache-to: ${{ inputs.enable-cache && format('type=gha,mode=max,scope={0}-{1}-{2}', github.repository, inputs.flavor, matrix.runner) || '' }}
72+
cache-from: ${{ inputs.enable-cache && format('type=gha,scope={0}-{1}-{2}', github.repository, inputs.flavor, matrix.runner) || '' }}
6873
- name: Export digest
6974
run: |
75+
set -Eeuo pipefail
7076
mkdir -p ${{ runner.temp }}/digests
71-
digest="${{ steps.build-and-push.outputs.digest }}"
72-
touch "${{ runner.temp }}/digests/${digest#sha256:}"
77+
touch "${{ runner.temp }}/digests/${DIGEST#sha256:}"
78+
env:
79+
DIGEST: ${{ steps.build-and-push.outputs.digest }}
7380
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
7481
with:
7582
name: digests-${{ inputs.flavor }}-${{ steps.devcontainer-arch.outputs.arch }}
@@ -123,15 +130,13 @@ jobs:
123130
type=semver,pattern={{major}}.{{minor}}
124131
type=semver,pattern={{major}}
125132
- name: Create manifest list and push
126-
working-directory: ${{ runner.temp }}/digests
127-
shell: python
128133
run: |
129134
import os
130135
import json
131136
import subprocess
132137
133-
CONTAINER = '${{ env.REGISTRY }}/${{ github.repository }}-${{ inputs.flavor }}'
134-
METADATA = json.loads('${{ steps.metadata.outputs.json }}')
138+
CONTAINER = f"{os.getenv('REGISTRY')}/${{ github.repository }}-{os.getenv('CONTAINER_FLAVOR')}"
139+
METADATA = json.loads(os.getenv('METADATA_JSON'))
135140
136141
digests = [f for f in os.listdir('.') if f.startswith('sha256:') or len(f) == 64]
137142
@@ -143,12 +148,18 @@ jobs:
143148
144149
print(' '.join(command))
145150
subprocess.run(command, check=True)
151+
env:
152+
METADATA_JSON: ${{ steps.metadata.outputs.json }}
153+
shell: python
154+
working-directory: ${{ runner.temp }}/digests
146155
- name: Inspect manifest and extract digest
147156
id: inspect-manifest
148157
run: |
149158
set -Eeuo pipefail
150-
output=$(docker buildx imagetools inspect ${{ env.REGISTRY }}/${{ github.repository }}-${{ inputs.flavor }}:${{ steps.metadata.outputs.version }} --format '{{json .}}')
159+
output=$(docker buildx imagetools inspect "${REGISTRY}/${{ github.repository }}-${CONTAINER_FLAVOR}:${CONTAINER_VERSION}" --format '{{json .}}')
151160
echo "digest=$(echo "$output" | jq -r '.manifest.digest // .manifests[0].digest')" >> "$GITHUB_OUTPUT"
161+
env:
162+
CONTAINER_VERSION: ${{ steps.metadata.outputs.version }}
152163
- uses: ./.github/actions/container-size-diff
153164
id: container-size-diff
154165
with:
@@ -170,7 +181,7 @@ jobs:
170181
show-summary: false
171182
push-to-registry: true
172183
- name: Verify attestation
184+
run: gh attestation verify --repo ${{ github.repository }} "oci://${REGISTRY}/${{ github.repository }}-${CONTAINER_FLAVOR}@${DIGEST}"
173185
env:
186+
DIGEST: ${{ steps.inspect-manifest.outputs.digest }}
174187
GH_TOKEN: ${{ github.token }}
175-
run: |
176-
gh attestation verify --repo ${{ github.repository }} oci://${{ env.REGISTRY }}/${{ github.repository }}-${{ inputs.flavor }}@${{ steps.inspect-manifest.outputs.digest }}

0 commit comments

Comments
 (0)