@@ -75,10 +75,18 @@ defaults:
7575 run :
7676 shell : bash
7777
78+ # Security policy: No ${{ }} expressions in `run:` blocks.
79+ # All expression values are assigned to `env:` and referenced as
80+ # shell variables. This prevents script injection from runtime values
81+ # (matrix outputs, secrets) and keeps the rule enforceable by zizmor
82+ # without per-expression exceptions.
83+
7884jobs :
7985 matrix :
8086 name : Image Matrix
8187 runs-on : ubuntu-latest
88+ permissions :
89+ contents : read
8290 outputs :
8391 platform-matrix : ${{ steps.images-by-platform.outputs.platform_matrix }}
8492 versions-matrix : ${{ steps.images-by-version.outputs.versions_matrix }}
@@ -94,15 +102,26 @@ jobs:
94102
95103 - name : Images by Version/Platform
96104 id : images-by-platform
105+ env :
106+ DEV_VERSIONS : ${{ inputs.dev-versions }}
107+ MATRIX_VERSIONS : ${{ inputs.matrix-versions }}
108+ CONTEXT : ${{ inputs.context }}
97109 run : |
98- echo "platform_matrix=$(bakery ci matrix --quiet --dev-versions ${{ inputs.dev-versions }} -- matrix-versions ${{ inputs.matrix-versions }} -- context ${{ inputs.context }} | jq --compact-output .)" >> $GITHUB_OUTPUT
110+ echo "platform_matrix=$(bakery ci matrix --quiet --dev-versions "$DEV_VERSIONS" -- matrix-versions "$MATRIX_VERSIONS" -- context "$CONTEXT" | jq --compact-output .)" >> $GITHUB_OUTPUT
99111 - name : Images by Version
100112 id : images-by-version
113+ env :
114+ DEV_VERSIONS : ${{ inputs.dev-versions }}
115+ MATRIX_VERSIONS : ${{ inputs.matrix-versions }}
116+ CONTEXT : ${{ inputs.context }}
101117 run : |
102- echo "versions_matrix=$(bakery ci matrix --quiet --dev-versions ${{ inputs.dev-versions }} -- matrix-versions ${{ inputs.matrix-versions }} -- exclude platform --context ${{ inputs.context }} | jq --compact-output .)" >> $GITHUB_OUTPUT
118+ echo "versions_matrix=$(bakery ci matrix --quiet --dev-versions "$DEV_VERSIONS" -- matrix-versions "$MATRIX_VERSIONS" -- exclude platform --context "$CONTEXT" | jq --compact-output .)" >> $GITHUB_OUTPUT
103119
104120 build-test :
105121 name : " Build/Test ${{ matrix.img.image }}:${{ matrix.img.version }} (${{ matrix.img.platform }})"
122+ permissions :
123+ contents : read
124+ packages : write
106125 needs : matrix
107126 strategy :
108127 fail-fast : false
@@ -141,18 +160,12 @@ jobs:
141160 # this step sets an output that we can reference later.
142161 - name : Filter Steps
143162 id : filter-steps
163+ env :
164+ HAS_DOCKER_HUB : ${{ secrets.DOCKER_HUB_ACCESS_TOKEN != '' }}
165+ HAS_AWS_ROLE : ${{ secrets.AWS_ROLE != '' }}
144166 run : |
145- if [ -n "${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}" ] ; then
146- echo "docker-hub=true" >> $GITHUB_OUTPUT
147- else
148- echo "docker-hub=false" >> $GITHUB_OUTPUT
149- fi
150-
151- if [ -n "${{ secrets.AWS_ROLE }}" ] ; then
152- echo "ecr=true" >> $GITHUB_OUTPUT
153- else
154- echo "ecr=false" >> $GITHUB_OUTPUT
155- fi
167+ echo "docker-hub=$HAS_DOCKER_HUB" >> $GITHUB_OUTPUT
168+ echo "ecr=$HAS_AWS_ROLE" >> $GITHUB_OUTPUT
156169
157170 - name : Login to GitHub Container Registry
158171 uses : docker/login-action@v4
@@ -190,35 +203,50 @@ jobs:
190203 - name : Build
191204 env :
192205 GIT_SHA : ${{ github.sha }}
206+ RETRY : ${{ inputs.retry }}
207+ IMAGE_NAME : ${{ matrix.img.image }}
208+ IMAGE_VERSION : ${{ matrix.img.version }}
209+ IMAGE_PLATFORM : ${{ matrix.img.platform }}
210+ DEV_VERSIONS : ${{ inputs.dev-versions }}
211+ MATRIX_VERSIONS : ${{ inputs.matrix-versions }}
212+ REGISTRY : ghcr.io/${{ github.repository_owner }}
213+ NORMALIZED_PLATFORM : ${{ steps.normalize-platform.outputs.platform }}
214+ CONTEXT : ${{ inputs.context }}
193215 # Cache-to is conditional on --push (handled by bakery internally)
194216 run : |
195- PLATFORM=${BUILD_PLATFORM#linux/} \
196217 bakery build \
197218 --strategy build --pull \
198- --retry ${{ inputs.retry }} \
199- --image-name ' ^${{ matrix.img.image }}$' \
200- --image-version ${{ matrix.img.version }} \
201- --image-platform ${{ matrix.img.platform }} \
202- --dev-versions ${{ inputs.dev-versions }} \
203- --matrix-versions ${{ inputs.matrix-versions }} \
204- --cache-registry "ghcr.io/${{ github.repository_owner }} " \
205- --temp-registry "ghcr.io/${{ github.repository_owner }} " \
206- --metadata-file "./${{ matrix.img.image }} -${{ matrix.img.version }} -${{ steps.normalize-platform.outputs.platform } }-metadata.json" \
207- --context ${{ inputs.context }} \
219+ --retry "$RETRY" \
220+ --image-name " ^${IMAGE_NAME}$" \
221+ --image-version "$IMAGE_VERSION" \
222+ --image-platform "$IMAGE_PLATFORM" \
223+ --dev-versions "$DEV_VERSIONS" \
224+ --matrix-versions "$MATRIX_VERSIONS" \
225+ --cache-registry "$REGISTRY " \
226+ --temp-registry "$REGISTRY " \
227+ --metadata-file "./${IMAGE_NAME} -${IMAGE_VERSION} -${NORMALIZED_PLATFORM }-metadata.json" \
228+ --context "$CONTEXT" \
208229 --push
209230 - name : Test
231+ env :
232+ IMAGE_NAME : ${{ matrix.img.image }}
233+ IMAGE_VERSION : ${{ matrix.img.version }}
234+ IMAGE_PLATFORM : ${{ matrix.img.platform }}
235+ DEV_VERSIONS : ${{ inputs.dev-versions }}
236+ MATRIX_VERSIONS : ${{ inputs.matrix-versions }}
237+ NORMALIZED_PLATFORM : ${{ steps.normalize-platform.outputs.platform }}
238+ CONTEXT : ${{ inputs.context }}
210239 run : |
211- PLATFORM=${BUILD_PLATFORM#linux/} \
212240 GOSS_PATH=${GITHUB_WORKSPACE}/tools/goss \
213241 DGOSS_PATH=${GITHUB_WORKSPACE}/tools/dgoss \
214242 bakery run dgoss \
215- --image-name ' ^${{ matrix.img.image }}$' \
216- --image-version ${{ matrix.img.version }} \
217- --image-platform ${{ matrix.img.platform }} \
218- --dev-versions ${{ inputs.dev-versions }} \
219- --matrix-versions ${{ inputs.matrix-versions }} \
220- --metadata-file "./${{ matrix.img.image }} -${{ matrix.img.version }} -${{ steps.normalize-platform.outputs.platform } }-metadata.json" \
221- --context ${{ inputs.context }}
243+ --image-name " ^${IMAGE_NAME}$" \
244+ --image-version "$IMAGE_VERSION" \
245+ --image-platform "$IMAGE_PLATFORM" \
246+ --dev-versions "$DEV_VERSIONS" \
247+ --matrix-versions "$MATRIX_VERSIONS" \
248+ --metadata-file "./${IMAGE_NAME} -${IMAGE_VERSION} -${NORMALIZED_PLATFORM }-metadata.json" \
249+ --context "$CONTEXT"
222250 - name : Upload Metadata
223251 uses : actions/upload-artifact@v7
224252 with :
@@ -228,6 +256,9 @@ jobs:
228256
229257 merge :
230258 name : " Merge/Push ${{ matrix.img.image }}:${{ matrix.img.version }}"
259+ permissions :
260+ contents : read
261+ packages : write
231262 needs :
232263 - matrix
233264 - build-test
@@ -260,18 +291,12 @@ jobs:
260291 # this step sets an output that we can reference later.
261292 - name : Filter Steps
262293 id : filter-steps
294+ env :
295+ HAS_DOCKER_HUB : ${{ secrets.DOCKER_HUB_ACCESS_TOKEN != '' }}
296+ HAS_AWS_ROLE : ${{ secrets.AWS_ROLE != '' }}
263297 run : |
264- if [ -n "${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}" ] ; then
265- echo "docker-hub=true" >> $GITHUB_OUTPUT
266- else
267- echo "docker-hub=false" >> $GITHUB_OUTPUT
268- fi
269-
270- if [ -n "${{ secrets.AWS_ROLE }}" ] ; then
271- echo "ecr=true" >> $GITHUB_OUTPUT
272- else
273- echo "ecr=false" >> $GITHUB_OUTPUT
274- fi
298+ echo "docker-hub=$HAS_DOCKER_HUB" >> $GITHUB_OUTPUT
299+ echo "ecr=$HAS_AWS_ROLE" >> $GITHUB_OUTPUT
275300
276301 - name : Login to GitHub Container Registry
277302 uses : docker/login-action@v4
@@ -318,15 +343,21 @@ jobs:
318343 - name : Merge/Push
319344 env :
320345 GIT_SHA : ${{ github.sha }}
346+ CONTEXT : ${{ inputs.context }}
347+ REGISTRY : ghcr.io/${{ github.repository_owner }}
348+ PUSH : ${{ inputs.push }}
321349 run : |
350+ if [ "$PUSH" = "true" ]; then PUSH_FLAG=""; else PUSH_FLAG="--dry-run"; fi
322351 bakery ci merge \
323- --context ${{ inputs.context }} \
324- --temp-registry "ghcr.io/${{ github.repository_owner }} " \
325- ${{ inputs.push && ' \' || '--dry-run \' }}
352+ --context "$CONTEXT" \
353+ --temp-registry "$REGISTRY " \
354+ $PUSH_FLAG \
326355 *-metadata.json
327356
328357 readme :
329358 name : Push READMEs
359+ permissions :
360+ contents : read
330361 if : ${{ inputs.push }}
331362 needs :
332363 - merge
@@ -345,8 +376,11 @@ jobs:
345376 env :
346377 DOCKER_HUB_README_USERNAME : ${{ secrets.DOCKER_HUB_README_USERNAME }}
347378 DOCKER_HUB_README_PASSWORD : ${{ secrets.DOCKER_HUB_README_PASSWORD }}
379+ CONTEXT : ${{ inputs.context }}
380+ DEV_VERSIONS : ${{ inputs.dev-versions }}
381+ MATRIX_VERSIONS : ${{ inputs.matrix-versions }}
348382 run : |
349383 bakery ci readme \
350- --context ${{ inputs.context }} \
351- --dev-versions ${{ inputs.dev-versions }} \
352- --matrix-versions ${{ inputs.matrix-versions }}
384+ --context "$CONTEXT" \
385+ --dev-versions "$DEV_VERSIONS" \
386+ --matrix-versions "$MATRIX_VERSIONS"
0 commit comments