From 326d9e58d79bd4ab78e27bbb9e2e3ea665ff2349 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 5 Nov 2025 11:26:41 -0500 Subject: [PATCH 1/3] ci: Use zizmor to fix and audit image publish action * Pin actions to digest * Replace template substitution with envs --- .github/workflows/publishImage.yml | 55 +++++++++++++++++++----------- 1 file changed, 36 insertions(+), 19 deletions(-) diff --git a/.github/workflows/publishImage.yml b/.github/workflows/publishImage.yml index 2b7244d5..1fdc77f9 100644 --- a/.github/workflows/publishImage.yml +++ b/.github/workflows/publishImage.yml @@ -62,13 +62,19 @@ jobs: # list all registries to push to and join all non-empty with comma # https://unix.stackexchange.com/a/693165/116849 # https://stackoverflow.com/a/9429887/1469797 - strings=("${{vars.DOCKERHUB_SLUG}}" "${{vars.GHCR_SLUG}}") + strings=("${VARS_DOCKERHUB_SLUG}" "${VARS_GHCR_SLUG}") for i in ${!strings[@]}; do [[ -z ${strings[i]} ]] && unset strings[i]; done joined_string=$(IFS=, ; echo "${strings[*]}") echo "REGISTRIES_JOINED=$joined_string" >> $GITHUB_ENV + env: + VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} + VARS_GHCR_SLUG: ${{vars.GHCR_SLUG}} + - name: Check out the repo - uses: actions/checkout@v4 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 #v4.3.0 + with: + persist-credentials: false - name: Set short git commit SHA id: appvars @@ -94,14 +100,14 @@ jobs: - name: Login to Docker Hub if: ${{ github.event_name != 'pull_request' && vars.DOCKERHUB_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: ${{ github.event_name != 'pull_request' && vars.GHCR_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -110,13 +116,13 @@ jobs: # metadata extract for docker labels/image names is done in merge job - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 #v3.11.1 # https://github.com/docker/build-push-action/issues/671#issuecomment-1619353328 # for caching - name: Build and push by digest id: build - uses: docker/build-push-action@v6 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 #v6.18.0 with: build-args: | APP_BUILD_VERSION=${{steps.appversion.outputs.appversion}} @@ -129,11 +135,12 @@ jobs: - name: Export digest run: | mkdir -p /tmp/digests - digest="${{ steps.build.outputs.digest }}" - touch "/tmp/digests/${digest#sha256:}" - + digest="${VARS_DIGEST}" + touch "/tmp/digests/${digest#sha256:}" + env: + VARS_DIGEST: ${{ steps.build.outputs.digest }} - name: Upload digest - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 #4.6.2 with: name: digests-${{ env.PLATFORM_PAIR }} path: /tmp/digests/* @@ -152,7 +159,7 @@ jobs: - test steps: - name: Download digests - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 #4.3.0 with: path: /tmp/digests pattern: digests-* @@ -160,25 +167,25 @@ jobs: - name: Login to Docker Hub if: ${{ github.event_name != 'pull_request' && vars.DOCKERHUB_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: ${{ github.event_name != 'pull_request' && vars.GHCR_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 - name: Extract metadata (tags, labels) id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 #5.9.0 with: images: | ${{ vars.DOCKERHUB_SLUG }} @@ -208,21 +215,31 @@ jobs: working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ vars.DOCKERHUB_SLUG }}@sha256:%s ' *) + $(printf '${VARS_DOCKERHUB_SLUG}@sha256:%s ' *) + env: + VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} - name: Create manifest list and push gchr if: ${{ vars.GHCR_SLUG != '' }} working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ vars.GHCR_SLUG }}@sha256:%s ' *) + $(printf '${VARS_GHCR_SLUG}@sha256:%s ' *) + env: + VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} - name: Inspect image dockerhub if: ${{ vars.DOCKERHUB_SLUG != '' }} run: | - docker buildx imagetools inspect ${{ vars.DOCKERHUB_SLUG }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${VARS_DOCKERHUB_SLUG}:${STEPS_META_OUTPUTS_VERSION} + env: + VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} + STEPS_META_OUTPUTS_VERSION: ${{ steps.meta.outputs.version }} - name: Inspect image ghcr if: ${{ vars.GHCR_SLUG != '' }} run: | - docker buildx imagetools inspect ${{ vars.GHCR_SLUG }}:${{ steps.meta.outputs.version }} \ No newline at end of file + docker buildx imagetools inspect ${VARS_GHCR_SLUG}:${STEPS_META_OUTPUTS_VERSION} + env: + VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} + STEPS_META_OUTPUTS_VERSION: ${{ steps.meta.outputs.version }} \ No newline at end of file -- 2.51.2 From 0427b6e94521201929a6263529407107a8f25731 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 5 Nov 2025 11:48:00 -0500 Subject: [PATCH 2/3] try with double quotes --- .github/workflows/publishImage.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publishImage.yml b/.github/workflows/publishImage.yml index 1fdc77f9..a0dae5c9 100644 --- a/.github/workflows/publishImage.yml +++ b/.github/workflows/publishImage.yml @@ -215,7 +215,7 @@ jobs: working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${VARS_DOCKERHUB_SLUG}@sha256:%s ' *) + $(printf "${VARS_DOCKERHUB_SLUG}@sha256:%s " *) env: VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} @@ -224,7 +224,7 @@ jobs: working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${VARS_GHCR_SLUG}@sha256:%s ' *) + $(printf "${VARS_GHCR_SLUG}@sha256:%s " *) env: VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} -- 2.51.2 From 7b36d95dfc7e723550f6dfc54dd565c7e3972ad7 Mon Sep 17 00:00:00 2001 From: FoxxMD Date: Wed, 5 Nov 2025 12:08:46 -0500 Subject: [PATCH 3/3] ci: Harden remaining workflows using zizmor * Pin action digests * Remove template injection where possible --- .github/workflows/docsDeploy.yml | 8 ++-- .github/workflows/packagesDeleteUntagged.yml | 2 +- .github/workflows/pr.yml | 45 +++++++++++++------- .github/workflows/testAndSanity.yml | 5 ++- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/.github/workflows/docsDeploy.yml b/.github/workflows/docsDeploy.yml index 08228ff4..6164660a 100644 --- a/.github/workflows/docsDeploy.yml +++ b/.github/workflows/docsDeploy.yml @@ -12,8 +12,10 @@ jobs: name: Deploy to GitHub Pages runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 #v4.3.0 + with: + persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #4.4.0 with: node-version: 20 cache: npm @@ -41,7 +43,7 @@ jobs: # Popular action to deploy to GitHub Pages: # Docs: https://github.com/peaceiris/actions-gh-pages#%EF%B8%8F-docusaurus - name: Deploy to GitHub Pages - uses: peaceiris/actions-gh-pages@v3 + uses: peaceiris/actions-gh-pages@373f7f263a76c20808c831209c920827a82a2847 #3.9.3 with: github_token: ${{ secrets.GITHUB_TOKEN }} # Build output to publish to the `gh-pages` branch: diff --git a/.github/workflows/packagesDeleteUntagged.yml b/.github/workflows/packagesDeleteUntagged.yml index 0eefdcde..9e7948c5 100644 --- a/.github/workflows/packagesDeleteUntagged.yml +++ b/.github/workflows/packagesDeleteUntagged.yml @@ -13,7 +13,7 @@ jobs: permissions: packages: write steps: - - uses: dataaxiom/ghcr-cleanup-action@v1 + - uses: dataaxiom/ghcr-cleanup-action@cd0cdb900b5dbf3a6f2cc869f0dbb0b8211f50c4 #1.0.16 with: token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index 7358cc31..fb107a15 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -48,10 +48,13 @@ jobs: # list all registries to push to and join all non-empty with comma # https://unix.stackexchange.com/a/693165/116849 # https://stackoverflow.com/a/9429887/1469797 - strings=("${{vars.DOCKERHUB_SLUG}}" "${{vars.GHCR_SLUG}}") + strings=("${VARS_DOCKERHUB_SLUG}" "${VARS_GHCR_SLUG}") for i in ${!strings[@]}; do [[ -z ${strings[i]} ]] && unset strings[i]; done joined_string=$(IFS=, ; echo "${strings[*]}") echo "REGISTRIES_JOINED=$joined_string" >> $GITHUB_ENV + env: + VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} + VARS_GHCR_SLUG: ${{vars.GHCR_SLUG}} # do not use here! # instead we can specify repo#sha in build-push-action so we only deal with foreign SHA for actually building image @@ -73,14 +76,14 @@ jobs: - name: Login to Docker Hub if: ${{ vars.DOCKERHUB_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: ${{ vars.GHCR_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} @@ -89,13 +92,13 @@ jobs: # metadata extract for docker labels/image names is done in merge job - name: Set up Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 #v3.11.1 # https://github.com/docker/build-push-action/issues/671#issuecomment-1619353328 # for caching - name: Build and push by digest id: build - uses: docker/build-push-action@v6 + uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 #v6.18.0 with: # specify foreign repo#sha from PR that is used to build image context: ${{github.event.pull_request.head.repo.clone_url}}#${{github.event.pull_request.head.sha}} @@ -114,7 +117,7 @@ jobs: touch "/tmp/digests/${digest#sha256:}" - name: Upload digest - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 #4.6.2 with: name: digests-${{ env.PLATFORM_PAIR }} path: /tmp/digests/* @@ -133,7 +136,7 @@ jobs: - test steps: - name: Download digests - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 #4.3.0 with: path: /tmp/digests pattern: digests-* @@ -141,25 +144,25 @@ jobs: - name: Login to Docker Hub if: ${{ vars.DOCKERHUB_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: username: ${{ secrets.DOCKER_USERNAME }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Login to GitHub Container Registry if: ${{ vars.GHCR_SLUG != '' }} - uses: docker/login-action@v3 + uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef # v3.6.0 with: registry: ghcr.io username: ${{ github.repository_owner }} password: ${{ secrets.GITHUB_TOKEN }} - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@e468171a9de216ec08956ac3ada2f0791b6bd435 - name: Extract metadata (tags, labels) id: meta - uses: docker/metadata-action@v5 + uses: docker/metadata-action@318604b99e75e41977312d83839a89be02ca4893 #5.9.0 with: images: | ${{ vars.DOCKERHUB_SLUG }} @@ -180,24 +183,34 @@ jobs: working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ vars.DOCKERHUB_SLUG }}@sha256:%s ' *) + $(printf "${VARS_DOCKERHUB_SLUG}@sha256:%s " *) + env: + VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} - name: Create manifest list and push gchr if: ${{ vars.GHCR_SLUG != '' }} working-directory: /tmp/digests run: | docker buildx imagetools create $(jq -cr '.tags | map("-t " + .) | join(" ")' <<< "$DOCKER_METADATA_OUTPUT_JSON") \ - $(printf '${{ vars.GHCR_SLUG }}@sha256:%s ' *) + $(printf "${VARS_GHCR_SLUG}@sha256:%s " *) + env: + VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} - name: Inspect image dockerhub if: ${{ vars.DOCKERHUB_SLUG != '' }} run: | - docker buildx imagetools inspect ${{ vars.DOCKERHUB_SLUG }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${VARS_DOCKERHUB_SLUG}:${STEPS_META_OUTPUTS_VERSION} + env: + VARS_DOCKERHUB_SLUG: ${{ vars.DOCKERHUB_SLUG }} + STEPS_META_OUTPUTS_VERSION: ${{ steps.meta.outputs.version }} - name: Inspect image ghcr if: ${{ vars.GHCR_SLUG != '' }} run: | - docker buildx imagetools inspect ${{ vars.GHCR_SLUG }}:${{ steps.meta.outputs.version }} + docker buildx imagetools inspect ${VARS_GHCR_SLUG}:${STEPS_META_OUTPUTS_VERSION} + env: + VARS_GHCR_SLUG: ${{ vars.GHCR_SLUG }} + STEPS_META_OUTPUTS_VERSION: ${{ steps.meta.outputs.version }} combine-and-comment: @@ -207,7 +220,7 @@ jobs: if: contains(github.event.pull_request.labels.*.name, 'safe to test') steps: - name: Create comment - uses: marocchino/sticky-pull-request-comment@v2 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 #2.9.4 with: recreate: true header: "pr-release" diff --git a/.github/workflows/testAndSanity.yml b/.github/workflows/testAndSanity.yml index b5c281ff..d240fae1 100644 --- a/.github/workflows/testAndSanity.yml +++ b/.github/workflows/testAndSanity.yml @@ -19,11 +19,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out the repo - uses: actions/checkout@v4 + uses: actions/checkout@08eba0b27e820071cde6df949e0beb9ba4906955 #v4.3.0 with: ref: ${{ inputs.ref }} + persist-credentials: false - name: Use Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #4.4.0 with: node-version: ${{ inputs.node-version }} cache: 'npm' -- 2.51.2