From 7b69f4d6d241d5d7d7e6dd284adfaa595ea7350f Mon Sep 17 00:00:00 2001 From: JOY Date: Sat, 19 Sep 2026 11:43:21 +0700 Subject: [PATCH 1/2] ci: pin workflow actions to commit SHAs (audit MD-28) The fork's CI and Docker-publish chain (which holds packages:write) referenced actions by mutable major tags, so a compromised upstream release could hijack the pipeline. Every external action used by the fork's own chain (deploy-docker, deploy-api-v2-docker, check-types, lint, unit-tests and the yarn-install/cache-checkout composite actions) is now pinned to the latest in-major release SHA with the version kept in a trailing comment. No major-version jumps. --- .github/actions/cache-checkout/action.yml | 4 ++-- .github/actions/yarn-install/action.yml | 14 +++++++------- .github/workflows/check-types.yml | 2 +- .github/workflows/deploy-api-v2-docker.yml | 8 ++++---- .github/workflows/deploy-docker.yml | 8 ++++---- .github/workflows/lint.yml | 2 +- .github/workflows/unit-tests.yml | 2 +- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index 8fd22c706ef..2934377cca1 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - name: Cache git checkout - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 id: cache-checkout with: path: | @@ -16,7 +16,7 @@ runs: key: git-checkout-${{ github.head_ref || github.ref_name }}-${{ github.event.pull_request.head.sha || github.sha }} - name: Checkout PR code (on cache miss) if: steps.cache-checkout.outputs.cache-hit != 'true' - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: ref: ${{ github.event.pull_request.head.sha || github.sha }} fetch-depth: 2 diff --git a/.github/actions/yarn-install/action.yml b/.github/actions/yarn-install/action.yml index e30334a1c94..e08840dfe9f 100644 --- a/.github/actions/yarn-install/action.yml +++ b/.github/actions/yarn-install/action.yml @@ -24,7 +24,7 @@ runs: using: "composite" steps: - name: Use Node ${{ inputs.node_version }} - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ inputs.node_version }} - name: Expose yarn config as "$GITHUB_OUTPUT" @@ -37,7 +37,7 @@ runs: # This avoids downloading ~1.2GB of cache data when we just want to verify caches exist - name: Check yarn cache (lookup-only) if: ${{ inputs.skip-install-if-cache-hit == 'true' }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 id: yarn-download-cache-check with: path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} @@ -46,7 +46,7 @@ runs: - name: Check node_modules cache (lookup-only) if: ${{ inputs.skip-install-if-cache-hit == 'true' }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 id: yarn-nm-cache-check with: path: | @@ -57,7 +57,7 @@ runs: - name: Check yarn install state cache (lookup-only) if: ${{ inputs.skip-install-if-cache-hit == 'true' }} - uses: actions/cache/restore@v4 + uses: actions/cache/restore@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 id: yarn-install-state-cache-check with: path: .yarn/ci-cache/ @@ -83,7 +83,7 @@ runs: # Only restore if not in skip mode, or if skip mode but any cache check missed - name: Restore yarn cache if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 id: yarn-download-cache with: path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} @@ -93,7 +93,7 @@ runs: - name: Restore node_modules if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} id: yarn-nm-cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 with: path: | **/node_modules/ @@ -104,7 +104,7 @@ runs: - name: Restore yarn install state if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} id: yarn-install-state-cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 with: path: .yarn/ci-cache/ key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }} diff --git a/.github/workflows/check-types.yml b/.github/workflows/check-types.yml index a9b788f62e8..e718a3cc11c 100644 --- a/.github/workflows/check-types.yml +++ b/.github/workflows/check-types.yml @@ -11,7 +11,7 @@ jobs: check-types: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: sparse-checkout: .github - uses: ./.github/actions/cache-checkout diff --git a/.github/workflows/deploy-api-v2-docker.yml b/.github/workflows/deploy-api-v2-docker.yml index effbc61280f..105df348d48 100644 --- a/.github/workflows/deploy-api-v2-docker.yml +++ b/.github/workflows/deploy-api-v2-docker.yml @@ -20,20 +20,20 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build and push API v2 image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ./apps/api/v2/Dockerfile diff --git a/.github/workflows/deploy-docker.yml b/.github/workflows/deploy-docker.yml index f082d345db3..0c164b0f57f 100644 --- a/.github/workflows/deploy-docker.yml +++ b/.github/workflows/deploy-docker.yml @@ -24,13 +24,13 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v3 + uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0 - name: Log in to GitHub Container Registry - uses: docker/login-action@v3 + uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3.7.0 with: registry: ghcr.io username: ${{ github.actor }} @@ -43,7 +43,7 @@ jobs: echo "image_name=${IMAGE_NAME,,}" >> $GITHUB_OUTPUT - name: Build and push Docker image - uses: docker/build-push-action@v6 + uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6.19.2 with: context: . file: ./Dockerfile diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 5c9af507afc..01e83316020 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: sparse-checkout: .github - uses: ./.github/actions/cache-checkout diff --git a/.github/workflows/unit-tests.yml b/.github/workflows/unit-tests.yml index 0bde8787d96..8ddd4d33005 100644 --- a/.github/workflows/unit-tests.yml +++ b/.github/workflows/unit-tests.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 20 runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: sparse-checkout: .github - uses: ./.github/actions/cache-checkout From b8276e748305e030e517f1f033477ff90f6d2960 Mon Sep 17 00:00:00 2001 From: JOY Date: Sat, 19 Sep 2026 11:52:53 +0700 Subject: [PATCH 2/2] ci: fix actions/cache SHA (was concatenated with setup-node's) --- .github/actions/cache-checkout/action.yml | 2 +- .github/actions/yarn-install/action.yml | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/actions/cache-checkout/action.yml b/.github/actions/cache-checkout/action.yml index 2934377cca1..59400ec63e2 100644 --- a/.github/actions/cache-checkout/action.yml +++ b/.github/actions/cache-checkout/action.yml @@ -4,7 +4,7 @@ runs: using: "composite" steps: - name: Cache git checkout - uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 id: cache-checkout with: path: | diff --git a/.github/actions/yarn-install/action.yml b/.github/actions/yarn-install/action.yml index e08840dfe9f..fcfc5fee73d 100644 --- a/.github/actions/yarn-install/action.yml +++ b/.github/actions/yarn-install/action.yml @@ -37,7 +37,7 @@ runs: # This avoids downloading ~1.2GB of cache data when we just want to verify caches exist - name: Check yarn cache (lookup-only) if: ${{ inputs.skip-install-if-cache-hit == 'true' }} - uses: actions/cache/restore@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 id: yarn-download-cache-check with: path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} @@ -46,7 +46,7 @@ runs: - name: Check node_modules cache (lookup-only) if: ${{ inputs.skip-install-if-cache-hit == 'true' }} - uses: actions/cache/restore@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 id: yarn-nm-cache-check with: path: | @@ -57,7 +57,7 @@ runs: - name: Check yarn install state cache (lookup-only) if: ${{ inputs.skip-install-if-cache-hit == 'true' }} - uses: actions/cache/restore@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 id: yarn-install-state-cache-check with: path: .yarn/ci-cache/ @@ -83,7 +83,7 @@ runs: # Only restore if not in skip mode, or if skip mode but any cache check missed - name: Restore yarn cache if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} - uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 id: yarn-download-cache with: path: ${{ steps.yarn-config.outputs.CACHE_FOLDER }} @@ -93,7 +93,7 @@ runs: - name: Restore node_modules if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} id: yarn-nm-cache - uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: | **/node_modules/ @@ -104,7 +104,7 @@ runs: - name: Restore yarn install state if: ${{ inputs.skip-install-if-cache-hit != 'true' || steps.all-caches-check.outputs.all-hit != 'true' }} id: yarn-install-state-cache - uses: actions/cache@0057852bfaa89a56745cba8642d1e84afbd3f7d6820020 # v4.3.0 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: .yarn/ci-cache/ key: ${{ runner.os }}-yarn-install-state-cache-${{ hashFiles('yarn.lock', '.yarnrc.yml') }}