From d1f8233a2b2c1078380346f5266ce41a3eda5f2d Mon Sep 17 00:00:00 2001 From: MaddyMicrosoft Date: Wed, 19 Aug 2026 17:15:22 +1000 Subject: [PATCH] Pin third-party GitHub Actions to commit SHAs (#615) Third-party actions were referenced by movable major tags (e.g. actions/checkout@v6). A tag can be repointed by the upstream owner or an attacker who compromises that action's repo, silently running new code in our CI - the class of supply-chain attack seen with tj-actions in 2025. Pin the externally-owned actions to the immutable commit SHA the tag resolves to, with the version kept in a trailing comment. Dependabot (github-actions ecosystem) updates both the SHA and the comment together, so they do not drift. Pinned: actions/checkout, actions/setup-node, actions/github-script, actions/stale, github/codeql-action (init/autobuild/analyze). Deliberately NOT pinned: azure/login and azure/powershell stay on @v3. These are our own actions used as test/provisioning tooling - the canary and integration suites exist to validate the current v3, so pinning them to a SHA would freeze what the tests exercise and cause them to drift from the released major. The supply-chain threat model (us attacking our own action's CI) does not apply. Co-authored-by: Maddison Das <272712104+MaddyMicrosoft@users.noreply.github.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .github/workflows/azure-login-canary.yml | 2 +- .github/workflows/azure-login-live-tests.yml | 50 ++++++++++---------- .github/workflows/ci.yml | 4 +- .github/workflows/codeql.yml | 8 ++-- .github/workflows/defaultLabels.yml | 6 +-- .github/workflows/markdownlint.yml | 4 +- 6 files changed, 37 insertions(+), 37 deletions(-) diff --git a/.github/workflows/azure-login-canary.yml b/.github/workflows/azure-login-canary.yml index 665e04432..23bc1405b 100644 --- a/.github/workflows/azure-login-canary.yml +++ b/.github/workflows/azure-login-canary.yml @@ -30,7 +30,7 @@ jobs: az --version - name: Check out repository - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: 'Az CLI login with subscription' uses: azure/login@v3 diff --git a/.github/workflows/azure-login-live-tests.yml b/.github/workflows/azure-login-live-tests.yml index 1d3657a95..1e102279c 100644 --- a/.github/workflows/azure-login-live-tests.yml +++ b/.github/workflows/azure-login-live-tests.yml @@ -55,10 +55,10 @@ jobs: steps: - name: 'Checking out repo code' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Set Node.js 24.x for GitHub Action - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x @@ -147,10 +147,10 @@ jobs: steps: - name: 'Checking out repo code' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Set Node.js 24.x for GitHub Action - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x @@ -280,10 +280,10 @@ jobs: environment: Automation test steps: - name: 'Checking out repo code' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Set Node.js 24.x for GitHub Action - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x @@ -363,10 +363,10 @@ jobs: steps: - name: 'Checking out repo code' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Set Node.js 24.x for GitHub Action - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x @@ -393,7 +393,7 @@ jobs: - name: Check Last step failed if: steps.cli_3.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -410,7 +410,7 @@ jobs: - name: Check Last step failed if: steps.ps_3.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -426,10 +426,10 @@ jobs: steps: - name: 'Checking out repo code' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Set Node.js 24.x for GitHub Action - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x @@ -448,7 +448,7 @@ jobs: - name: Check Last step failed if: steps.login_4.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -463,7 +463,7 @@ jobs: - name: Check Last step failed if: steps.login_5.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -477,7 +477,7 @@ jobs: - name: Check Last step failed if: steps.login_6.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -493,7 +493,7 @@ jobs: - name: Check Last step failed if: steps.login_7.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -510,7 +510,7 @@ jobs: - name: Check Last step failed if: steps.login_8.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -538,7 +538,7 @@ jobs: - name: Check Last step failed if: steps.ps_8.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -566,7 +566,7 @@ jobs: - name: Check Last step failed if: steps.ps_9.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -585,7 +585,7 @@ jobs: - name: Check Last step failed if: steps.login_10.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -602,7 +602,7 @@ jobs: - name: Check Last step failed if: steps.login_11.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -622,7 +622,7 @@ jobs: - name: Check Last step failed if: steps.login_12.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -638,7 +638,7 @@ jobs: - name: Check Last step failed if: steps.login_13.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -654,7 +654,7 @@ jobs: - name: Check Last step failed if: steps.login_14.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') @@ -669,7 +669,7 @@ jobs: - name: Check Last step failed if: steps.login_15.outcome == 'success' - uses: actions/github-script@v7 + uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7.1.0 with: script: | core.setFailed('Last action should fail but not. Please check it.') diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f128428c8..09aede1f1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,10 +18,10 @@ jobs: steps: - name: 'Checking out repo code' - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Set Node.js 24.x for GitHub Action - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 0ccb3a2ff..793db6d20 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -19,18 +19,18 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v3 + uses: github/codeql-action/init@f3712979fa5f215279b101dd0a2e3bdfb4353324 # v3.37.7 with: languages: javascript # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - name: Autobuild - uses: github/codeql-action/autobuild@v3 + uses: github/codeql-action/autobuild@f3712979fa5f215279b101dd0a2e3bdfb4353324 # v3.37.7 # â„šī¸ Command-line programs to run using the OS shell. # 📚 https://git.io/JvXDl @@ -44,4 +44,4 @@ jobs: # make release - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + uses: github/codeql-action/analyze@f3712979fa5f215279b101dd0a2e3bdfb4353324 # v3.37.7 diff --git a/.github/workflows/defaultLabels.yml b/.github/workflows/defaultLabels.yml index b9c165487..c190f060f 100644 --- a/.github/workflows/defaultLabels.yml +++ b/.github/workflows/defaultLabels.yml @@ -14,7 +14,7 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: - - uses: actions/stale@v8 + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 name: Setting issue as idle with: repo-token: ${{ secrets.GITHUB_TOKEN }} @@ -25,7 +25,7 @@ jobs: operations-per-run: 100 exempt-issue-labels: 'backlog' - - uses: actions/stale@v8 + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 name: Setting PR as idle with: repo-token: ${{ secrets.GITHUB_TOKEN }} @@ -35,7 +35,7 @@ jobs: days-before-close: -1 operations-per-run: 100 - - uses: actions/stale@v8 + - uses: actions/stale@1160a2240286f5da8ec72b1c0816ce2481aabf84 # v8.0.0 name: Close issue with no feedback for 20 days with: repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/markdownlint.yml b/.github/workflows/markdownlint.yml index 5c13f1674..2f1fdf314 100644 --- a/.github/workflows/markdownlint.yml +++ b/.github/workflows/markdownlint.yml @@ -7,9 +7,9 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 + - uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 - name: Use Node.js - uses: actions/setup-node@v6 + uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6.5.0 with: node-version: 24.x - name: Run Markdownlint