Skip to content

chore(deps): update github/codeql-action action to v4.36.2#335

Open
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/github-codeql-action-4-x
Open

chore(deps): update github/codeql-action action to v4.36.2#335
renovate[bot] wants to merge 1 commit into
mainfrom
renovate/github-codeql-action-4-x

Conversation

@renovate

@renovate renovate Bot commented Jun 16, 2026

Copy link
Copy Markdown
Contributor

This PR contains the following updates:

Package Type Update Change
github/codeql-action action patch v4.36.0v4.36.2

Release Notes

github/codeql-action (github/codeql-action)

v4.36.2

Compare Source

  • Cache CodeQL CLI version information across Actions steps. #​3943
  • Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. #​3937
  • Update default CodeQL bundle version to 2.25.6. #​3948

v4.36.1

Compare Source

No user facing changes.


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Enabled.

Rebasing: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot requested a review from onyb as a code owner June 16, 2026 09:56
@renovate renovate Bot changed the title chore(deps): update github/codeql-action action to v4.36.2 chore(deps): update github/codeql-action action to v4.36.1 Jun 16, 2026
@renovate renovate Bot force-pushed the renovate/github-codeql-action-4-x branch 4 times, most recently from 279e2a8 to 9835fe6 Compare June 18, 2026 18:00
@renovate renovate Bot changed the title chore(deps): update github/codeql-action action to v4.36.1 chore(deps): update github/codeql-action action to v4.36.2 Jun 18, 2026
@renovate renovate Bot force-pushed the renovate/github-codeql-action-4-x branch 3 times, most recently from 60ea49e to dc0d011 Compare June 20, 2026 01:38
@renovate renovate Bot force-pushed the renovate/github-codeql-action-4-x branch from dc0d011 to 7594b65 Compare June 21, 2026 01:46
@github-actions

Copy link
Copy Markdown
Contributor

[puLL-Merge] - github/codeql-action@v4.36.0..v4.36.2

Diff
diff --git .github/actions/release-initialise/action.yml .github/actions/release-initialise/action.yml
index b3eda48f6b..057d5a5b6d 100644
--- .github/actions/release-initialise/action.yml
+++ .github/actions/release-initialise/action.yml
@@ -16,13 +16,13 @@ runs:
       shell: bash
 
     - name: Set up Node
-      uses: actions/setup-node@v6
+      uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
       with:
         node-version: 24
         cache: 'npm'
 
     - name: Set up Python
-      uses: actions/setup-python@v6
+      uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
       with:
         python-version: '3.12'
 
diff --git .github/workflows/__all-platform-bundle.yml .github/workflows/__all-platform-bundle.yml
index 1be1d63758..648679b7bf 100644
--- .github/workflows/__all-platform-bundle.yml
+++ .github/workflows/__all-platform-bundle.yml
@@ -74,13 +74,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__analysis-kinds.yml .github/workflows/__analysis-kinds.yml
index 1e43775fff..504c1fcc6e 100644
--- .github/workflows/__analysis-kinds.yml
+++ .github/workflows/__analysis-kinds.yml
@@ -72,7 +72,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -92,7 +92,7 @@ jobs:
           post-processed-sarif-path: '${{ runner.temp }}/post-processed'
 
       - name: Upload SARIF files
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: |
             analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
@@ -100,7 +100,7 @@ jobs:
           retention-days: 7
 
       - name: Upload post-processed SARIF
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: |
             post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
@@ -110,7 +110,7 @@ jobs:
 
       - name: Check quality query does not appear in security SARIF
         if: contains(matrix.analysis-kinds, 'code-scanning')
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: '${{ runner.temp }}/results/javascript.sarif'
           EXPECT_PRESENT: 'false'
@@ -118,7 +118,7 @@ jobs:
           script: ${{ env.CHECK_SCRIPT }}
       - name: Check quality query appears in quality SARIF
         if: contains(matrix.analysis-kinds, 'code-quality')
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: '${{ runner.temp }}/results/javascript.quality.sarif'
           EXPECT_PRESENT: 'true'
diff --git .github/workflows/__analyze-ref-input.yml .github/workflows/__analyze-ref-input.yml
index 9ad6c3ec7c..5f4bb4d04a 100644
--- .github/workflows/__analyze-ref-input.yml
+++ .github/workflows/__analyze-ref-input.yml
@@ -70,13 +70,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__autobuild-action.yml .github/workflows/__autobuild-action.yml
index 7521614f2c..f8cd1275d7 100644
--- .github/workflows/__autobuild-action.yml
+++ .github/workflows/__autobuild-action.yml
@@ -64,9 +64,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Prepare test
diff --git .github/workflows/__autobuild-direct-tracing-with-working-dir.yml .github/workflows/__autobuild-direct-tracing-with-working-dir.yml
index 8acd90253f..d0a4e7d783 100644
--- .github/workflows/__autobuild-direct-tracing-with-working-dir.yml
+++ .github/workflows/__autobuild-direct-tracing-with-working-dir.yml
@@ -66,9 +66,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Java
-        uses: actions/setup-java@v5
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
         with:
           java-version: ${{ inputs.java-version || '17' }}
           distribution: temurin
diff --git .github/workflows/__autobuild-working-dir.yml .github/workflows/__autobuild-working-dir.yml
index c9fb1e9e9c..f9718baf7b 100644
--- .github/workflows/__autobuild-working-dir.yml
+++ .github/workflows/__autobuild-working-dir.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__build-mode-autobuild.yml .github/workflows/__build-mode-autobuild.yml
index 7619d45936..f22f642e6b 100644
--- .github/workflows/__build-mode-autobuild.yml
+++ .github/workflows/__build-mode-autobuild.yml
@@ -66,9 +66,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Java
-        uses: actions/setup-java@v5
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # v5.2.0
         with:
           java-version: ${{ inputs.java-version || '17' }}
           distribution: temurin
diff --git .github/workflows/__build-mode-manual.yml .github/workflows/__build-mode-manual.yml
index 93010fe636..515e28223c 100644
--- .github/workflows/__build-mode-manual.yml
+++ .github/workflows/__build-mode-manual.yml
@@ -70,13 +70,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__build-mode-none.yml .github/workflows/__build-mode-none.yml
index 5611d23811..4aff835887 100644
--- .github/workflows/__build-mode-none.yml
+++ .github/workflows/__build-mode-none.yml
@@ -52,7 +52,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__build-mode-rollback.yml .github/workflows/__build-mode-rollback.yml
index b4dd4041bb..f7c4d090e6 100644
--- .github/workflows/__build-mode-rollback.yml
+++ .github/workflows/__build-mode-rollback.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__bundle-from-nightly.yml .github/workflows/__bundle-from-nightly.yml
index a7dc934a0a..5499696453 100644
--- .github/workflows/__bundle-from-nightly.yml
+++ .github/workflows/__bundle-from-nightly.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__bundle-from-toolcache.yml .github/workflows/__bundle-from-toolcache.yml
index 4c7f21a32b..389981985c 100644
--- .github/workflows/__bundle-from-toolcache.yml
+++ .github/workflows/__bundle-from-toolcache.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -62,7 +62,7 @@ jobs:
         run: npm install @actions/tool-cache@3
       - name: Check toolcache contains CodeQL
         continue-on-error: true
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         with:
           script: |
             const toolcache = require('@actions/tool-cache');
@@ -75,7 +75,7 @@ jobs:
         with:
           tools: ${{ steps.prepare-test.outputs.tools-url }}
       - name: Check CodeQL is installed within the toolcache
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         with:
           script: |
             const toolcache = require('@actions/tool-cache');
diff --git .github/workflows/__bundle-toolcache.yml .github/workflows/__bundle-toolcache.yml
index 7606475875..7e83829d6a 100644
--- .github/workflows/__bundle-toolcache.yml
+++ .github/workflows/__bundle-toolcache.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -63,7 +63,7 @@ jobs:
           use-all-platform-bundle: 'false'
           setup-kotlin: 'true'
       - name: Remove CodeQL from toolcache
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         with:
           script: |
             const fs = require('fs');
@@ -73,7 +73,7 @@ jobs:
       - name: Install @actions/tool-cache
         run: npm install @actions/tool-cache@3
       - name: Check toolcache does not contain CodeQL
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         with:
           script: |
             const toolcache = require('@actions/tool-cache');
@@ -92,7 +92,7 @@ jobs:
           output: ${{ runner.temp }}/results
           upload-database: false
       - name: Check CodeQL is installed within the toolcache
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         with:
           script: |
             const toolcache = require('@actions/tool-cache');
diff --git .github/workflows/__bundle-zstd.yml .github/workflows/__bundle-zstd.yml
index 85e0695268..45cf73a0ed 100644
--- .github/workflows/__bundle-zstd.yml
+++ .github/workflows/__bundle-zstd.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -63,7 +63,7 @@ jobs:
           use-all-platform-bundle: 'false'
           setup-kotlin: 'true'
       - name: Remove CodeQL from toolcache
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         with:
           script: |
             const fs = require('fs');
@@ -82,13 +82,13 @@ jobs:
           output: ${{ runner.temp }}/results
           upload-database: false
       - name: Upload SARIF
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: ${{ matrix.os }}-zstd-bundle.sarif
           path: ${{ runner.temp }}/results/javascript.sarif
           retention-days: 7
       - name: Check diagnostic with expected tools URL appears in SARIF
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
         with:
diff --git .github/workflows/__cleanup-db-cluster-dir.yml .github/workflows/__cleanup-db-cluster-dir.yml
index cc41fea77a..249a1f81b6 100644
--- .github/workflows/__cleanup-db-cluster-dir.yml
+++ .github/workflows/__cleanup-db-cluster-dir.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__config-export.yml .github/workflows/__config-export.yml
index 24549dd186..e359764bdd 100644
--- .github/workflows/__config-export.yml
+++ .github/workflows/__config-export.yml
@@ -52,7 +52,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -70,13 +70,13 @@ jobs:
           output: '${{ runner.temp }}/results'
           upload-database: false
       - name: Upload SARIF
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
           path: '${{ runner.temp }}/results/javascript.sarif'
           retention-days: 7
       - name: Check config properties appear in SARIF
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: '${{ runner.temp }}/results/javascript.sarif'
         with:
diff --git .github/workflows/__config-input.yml .github/workflows/__config-input.yml
index a2e4dba2c3..2a82e9aa5c 100644
--- .github/workflows/__config-input.yml
+++ .github/workflows/__config-input.yml
@@ -50,9 +50,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 20.x
           cache: npm
diff --git .github/workflows/__cpp-deptrace-disabled.yml .github/workflows/__cpp-deptrace-disabled.yml
index c73161cd8a..9e44285198 100644
--- .github/workflows/__cpp-deptrace-disabled.yml
+++ .github/workflows/__cpp-deptrace-disabled.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__cpp-deptrace-enabled-on-macos.yml .github/workflows/__cpp-deptrace-enabled-on-macos.yml
index d2cce49369..825d4acd99 100644
--- .github/workflows/__cpp-deptrace-enabled-on-macos.yml
+++ .github/workflows/__cpp-deptrace-enabled-on-macos.yml
@@ -52,7 +52,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__cpp-deptrace-enabled.yml .github/workflows/__cpp-deptrace-enabled.yml
index 0539d4ce60..c4ac54f3db 100644
--- .github/workflows/__cpp-deptrace-enabled.yml
+++ .github/workflows/__cpp-deptrace-enabled.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__diagnostics-export.yml .github/workflows/__diagnostics-export.yml
index bdf6b0aee1..418517a159 100644
--- .github/workflows/__diagnostics-export.yml
+++ .github/workflows/__diagnostics-export.yml
@@ -52,7 +52,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -81,13 +81,13 @@ jobs:
           output: '${{ runner.temp }}/results'
           upload-database: false
       - name: Upload SARIF
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
           path: '${{ runner.temp }}/results/javascript.sarif'
           retention-days: 7
       - name: Check diagnostics appear in SARIF
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: '${{ runner.temp }}/results/javascript.sarif'
         with:
diff --git .github/workflows/__export-file-baseline-information.yml .github/workflows/__export-file-baseline-information.yml
index 359461007d..18fcfafe08 100644
--- .github/workflows/__export-file-baseline-information.yml
+++ .github/workflows/__export-file-baseline-information.yml
@@ -74,13 +74,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
@@ -102,7 +102,7 @@ jobs:
         with:
           output: '${{ runner.temp }}/results'
       - name: Upload SARIF
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
           path: '${{ runner.temp }}/results/javascript.sarif'
diff --git .github/workflows/__extractor-ram-threads.yml .github/workflows/__extractor-ram-threads.yml
index eee08de580..a647124bcc 100644
--- .github/workflows/__extractor-ram-threads.yml
+++ .github/workflows/__extractor-ram-threads.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__global-proxy.yml .github/workflows/__global-proxy.yml
index 08c4ad64af..df544fb68a 100644
--- .github/workflows/__global-proxy.yml
+++ .github/workflows/__global-proxy.yml
@@ -52,7 +52,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__go-custom-queries.yml .github/workflows/__go-custom-queries.yml
index cc11dc941d..a595300652 100644
--- .github/workflows/__go-custom-queries.yml
+++ .github/workflows/__go-custom-queries.yml
@@ -72,13 +72,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__go-indirect-tracing-workaround-diagnostic.yml .github/workflows/__go-indirect-tracing-workaround-diagnostic.yml
index e474e1b6f5..2415c7ff8e 100644
--- .github/workflows/__go-indirect-tracing-workaround-diagnostic.yml
+++ .github/workflows/__go-indirect-tracing-workaround-diagnostic.yml
@@ -60,9 +60,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
@@ -78,7 +78,7 @@ jobs:
           languages: go
           tools: ${{ steps.prepare-test.outputs.tools-url }}
       # Deliberately change Go after the `init` step
-      - uses: actions/setup-go@v6
+      - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: '1.20'
       - name: Build code
@@ -88,7 +88,7 @@ jobs:
           output: '${{ runner.temp }}/results'
           upload-database: false
       - name: Check diagnostic appears in SARIF
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: '${{ runner.temp }}/results/go.sarif'
         with:
diff --git .github/workflows/__go-indirect-tracing-workaround-no-file-program.yml .github/workflows/__go-indirect-tracing-workaround-no-file-program.yml
index cc94d3bb8a..38718fba2c 100644
--- .github/workflows/__go-indirect-tracing-workaround-no-file-program.yml
+++ .github/workflows/__go-indirect-tracing-workaround-no-file-program.yml
@@ -60,9 +60,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
@@ -89,7 +89,7 @@ jobs:
           output: '${{ runner.temp }}/results'
           upload-database: false
       - name: Check diagnostic appears in SARIF
-        uses: actions/github-script@v8
+        uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
         env:
           SARIF_PATH: '${{ runner.temp }}/results/go.sarif'
         with:
diff --git .github/workflows/__go-indirect-tracing-workaround.yml .github/workflows/__go-indirect-tracing-workaround.yml
index 6c8a24e0c9..754299d3ed 100644
--- .github/workflows/__go-indirect-tracing-workaround.yml
+++ .github/workflows/__go-indirect-tracing-workaround.yml
@@ -60,9 +60,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__go-tracing-autobuilder.yml .github/workflows/__go-tracing-autobuilder.yml
index f44a512f85..5c96e28f11 100644
--- .github/workflows/__go-tracing-autobuilder.yml
+++ .github/workflows/__go-tracing-autobuilder.yml
@@ -80,9 +80,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__go-tracing-custom-build-steps.yml .github/workflows/__go-tracing-custom-build-steps.yml
index aae22d8c01..7d3ea3aea0 100644
--- .github/workflows/__go-tracing-custom-build-steps.yml
+++ .github/workflows/__go-tracing-custom-build-steps.yml
@@ -80,9 +80,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__go-tracing-legacy-workflow.yml .github/workflows/__go-tracing-legacy-workflow.yml
index cce0102575..68012f0d4d 100644
--- .github/workflows/__go-tracing-legacy-workflow.yml
+++ .github/workflows/__go-tracing-legacy-workflow.yml
@@ -80,9 +80,9 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__init-with-registries.yml .github/workflows/__init-with-registries.yml
index 940784361d..2c55e14e4a 100644
--- .github/workflows/__init-with-registries.yml
+++ .github/workflows/__init-with-registries.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__javascript-source-root.yml .github/workflows/__javascript-source-root.yml
index dc1a395ce9..31662fc166 100644
--- .github/workflows/__javascript-source-root.yml
+++ .github/workflows/__javascript-source-root.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__job-run-uuid-sarif.yml .github/workflows/__job-run-uuid-sarif.yml
index a10ccd1d1d..c0fa820e52 100644
--- .github/workflows/__job-run-uuid-sarif.yml
+++ .github/workflows/__job-run-uuid-sarif.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -67,7 +67,7 @@ jobs:
         with:
           output: '${{ runner.temp }}/results'
       - name: Upload SARIF
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
           path: '${{ runner.temp }}/results/javascript.sarif'
diff --git .github/workflows/__language-aliases.yml .github/workflows/__language-aliases.yml
index a4cdb034bf..fe9ebef9c3 100644
--- .github/workflows/__language-aliases.yml
+++ .github/workflows/__language-aliases.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__local-bundle.yml .github/workflows/__local-bundle.yml
index 50eb333492..a6ab9f523f 100644
--- .github/workflows/__local-bundle.yml
+++ .github/workflows/__local-bundle.yml
@@ -70,13 +70,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__multi-language-autodetect.yml .github/workflows/__multi-language-autodetect.yml
index 8115b66ee2..f4849b9903 100644
--- .github/workflows/__multi-language-autodetect.yml
+++ .github/workflows/__multi-language-autodetect.yml
@@ -104,13 +104,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
@@ -125,7 +125,7 @@ jobs:
         # We need Python 3.13 for older CLI versions because they are not compatible with Python 3.14 or newer.
         # See https://github.com/github/codeql-action/pull/3212
         if: matrix.version != 'nightly-latest' && matrix.version != 'linked'
-        uses: actions/setup-python@v6
+        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
         with:
           python-version: '3.13'
 
diff --git .github/workflows/__overlay-init-fallback.yml .github/workflows/__overlay-init-fallback.yml
index 0871e6b44b..554e9defcc 100644
--- .github/workflows/__overlay-init-fallback.yml
+++ .github/workflows/__overlay-init-fallback.yml
@@ -52,7 +52,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__packaging-codescanning-config-inputs-js.yml .github/workflows/__packaging-codescanning-config-inputs-js.yml
index 94280eeedb..9c7d842293 100644
--- .github/workflows/__packaging-codescanning-config-inputs-js.yml
+++ .github/workflows/__packaging-codescanning-config-inputs-js.yml
@@ -74,18 +74,18 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
       - name: Install Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 20.x
           cache: npm
diff --git .github/workflows/__packaging-config-inputs-js.yml .github/workflows/__packaging-config-inputs-js.yml
index 146bc43552..c446c7ff36 100644
--- .github/workflows/__packaging-config-inputs-js.yml
+++ .github/workflows/__packaging-config-inputs-js.yml
@@ -74,18 +74,18 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
       - name: Install Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 20.x
           cache: npm
diff --git .github/workflows/__packaging-config-js.yml .github/workflows/__packaging-config-js.yml
index fddd971f39..e550e493d5 100644
--- .github/workflows/__packaging-config-js.yml
+++ .github/workflows/__packaging-config-js.yml
@@ -74,18 +74,18 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
       - name: Install Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 20.x
           cache: npm
diff --git .github/workflows/__packaging-inputs-js.yml .github/workflows/__packaging-inputs-js.yml
index 64bd575d55..7d3450d04b 100644
--- .github/workflows/__packaging-inputs-js.yml
+++ .github/workflows/__packaging-inputs-js.yml
@@ -74,18 +74,18 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
       - name: Install Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 20.x
           cache: npm
diff --git .github/workflows/__remote-config.yml .github/workflows/__remote-config.yml
index 4302583d73..277f9293e9 100644
--- .github/workflows/__remote-config.yml
+++ .github/workflows/__remote-config.yml
@@ -72,13 +72,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__resolve-environment-action.yml .github/workflows/__resolve-environment-action.yml
index 982e4e7152..05125ca107 100644
--- .github/workflows/__resolve-environment-action.yml
+++ .github/workflows/__resolve-environment-action.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__rubocop-multi-language.yml .github/workflows/__rubocop-multi-language.yml
index 4e0fabe536..055aae50bc 100644
--- .github/workflows/__rubocop-multi-language.yml
+++ .github/workflows/__rubocop-multi-language.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -59,7 +59,7 @@ jobs:
           use-all-platform-bundle: 'false'
           setup-kotlin: 'true'
       - name: Set up Ruby
-        uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
+        uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0
         with:
           ruby-version: 2.6
       - name: Install Code Scanning integration
diff --git .github/workflows/__ruby.yml .github/workflows/__ruby.yml
index 6d326ee887..b8d556e534 100644
--- .github/workflows/__ruby.yml
+++ .github/workflows/__ruby.yml
@@ -60,7 +60,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__rust.yml .github/workflows/__rust.yml
index 1c3d18d16e..91c3d6618e 100644
--- .github/workflows/__rust.yml
+++ .github/workflows/__rust.yml
@@ -58,7 +58,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__split-workflow.yml .github/workflows/__split-workflow.yml
index 7dfa812499..64efae65f2 100644
--- .github/workflows/__split-workflow.yml
+++ .github/workflows/__split-workflow.yml
@@ -80,13 +80,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__start-proxy.yml .github/workflows/__start-proxy.yml
index 70ec13c96b..7a318b0233 100644
--- .github/workflows/__start-proxy.yml
+++ .github/workflows/__start-proxy.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__submit-sarif-failure.yml .github/workflows/__submit-sarif-failure.yml
index 2fdfeddfbf..03ea2de232 100644
--- .github/workflows/__submit-sarif-failure.yml
+++ .github/workflows/__submit-sarif-failure.yml
@@ -54,7 +54,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
@@ -62,7 +62,7 @@ jobs:
           version: ${{ matrix.version }}
           use-all-platform-bundle: 'false'
           setup-kotlin: 'true'
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - uses: ./init
         with:
           languages: javascript
diff --git .github/workflows/__swift-autobuild.yml .github/workflows/__swift-autobuild.yml
index cd26309f4e..4962547032 100644
--- .github/workflows/__swift-autobuild.yml
+++ .github/workflows/__swift-autobuild.yml
@@ -50,7 +50,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
diff --git .github/workflows/__swift-custom-build.yml .github/workflows/__swift-custom-build.yml
index efdbde7215..83c06ffd09 100644
--- .github/workflows/__swift-custom-build.yml
+++ .github/workflows/__swift-custom-build.yml
@@ -74,13 +74,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__unset-environment.yml .github/workflows/__unset-environment.yml
index 535362e836..b519e01dd6 100644
--- .github/workflows/__unset-environment.yml
+++ .github/workflows/__unset-environment.yml
@@ -72,13 +72,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__upload-ref-sha-input.yml .github/workflows/__upload-ref-sha-input.yml
index 4e95021495..9a1c91dea9 100644
--- .github/workflows/__upload-ref-sha-input.yml
+++ .github/workflows/__upload-ref-sha-input.yml
@@ -70,13 +70,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__upload-sarif.yml .github/workflows/__upload-sarif.yml
index 547828d072..182adbfdea 100644
--- .github/workflows/__upload-sarif.yml
+++ .github/workflows/__upload-sarif.yml
@@ -77,13 +77,13 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
diff --git .github/workflows/__with-checkout-path.yml .github/workflows/__with-checkout-path.yml
index 0d97287577..3d6380462b 100644
--- .github/workflows/__with-checkout-path.yml
+++ .github/workflows/__with-checkout-path.yml
@@ -71,13 +71,13 @@ jobs:
     steps:
       # This ensures we don't accidentally use the original checkout for any part of the test.
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: ${{ inputs.dotnet-version || '9.x' }}
       - name: Install Go
-        uses: actions/setup-go@v6
+        uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ${{ inputs.go-version || '>=1.21.0' }}
           cache: false
@@ -96,7 +96,7 @@ jobs:
           rm -rf ./* .github .git
       # Check out the actions repo again, but at a different location.
       # choose an arbitrary SHA so that we can later test that the commit_oid is not from main
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           ref: 474bbf07f9247ffe1856c6a0f94aeeb10e7afee6
           path: x/y/z/some-path
diff --git .github/workflows/check-expected-release-files.yml .github/workflows/check-expected-release-files.yml
index 79ce600711..ee6ad120bc 100644
--- .github/workflows/check-expected-release-files.yml
+++ .github/workflows/check-expected-release-files.yml
@@ -26,7 +26,7 @@ jobs:
 
     steps:
       - name: Checkout CodeQL Action
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Check Expected Release Files
         run: |
           bundle_version="$(cat "./src/defaults.json" | jq -r ".bundleVersion")"
diff --git .github/workflows/codeql.yml .github/workflows/codeql.yml
index 9f14b05bf3..d604bbd80e 100644
--- .github/workflows/codeql.yml
+++ .github/workflows/codeql.yml
@@ -35,7 +35,7 @@ jobs:
       security-events: read
 
     steps:
-    - uses: actions/checkout@v6
+    - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
     - name: Set up default CodeQL bundle
       id: setup-default
       uses: ./setup-codeql
@@ -87,7 +87,7 @@ jobs:
 
     steps:
     - name: Checkout
-      uses: actions/checkout@v6
+      uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
     - name: Initialize CodeQL
       uses: ./init
       id: init
@@ -124,7 +124,7 @@ jobs:
 
     steps:
     - name: Checkout
-      uses: actions/checkout@v6
+      uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
     - name: Initialize CodeQL
       uses: ./init
       with:
diff --git .github/workflows/codescanning-config-cli.yml .github/workflows/codescanning-config-cli.yml
index 0da0f4d38f..3a62bd78d3 100644
--- .github/workflows/codescanning-config-cli.yml
+++ .github/workflows/codescanning-config-cli.yml
@@ -59,10 +59,10 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
     - name: Check out repository
-      uses: actions/checkout@v6
+      uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
     - name: Set up Node.js
-      uses: actions/setup-node@v6
+      uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
       with:
         node-version: 24
         cache: 'npm'
diff --git .github/workflows/debug-artifacts-failure-safe.yml .github/workflows/debug-artifacts-failure-safe.yml
index 5bb53ecbd6..d044d8420a 100644
--- .github/workflows/debug-artifacts-failure-safe.yml
+++ .github/workflows/debug-artifacts-failure-safe.yml
@@ -53,17 +53,17 @@ jobs:
       - name: Dump GitHub event
         run: cat "${GITHUB_EVENT_PATH}"
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
         with:
           version: ${{ matrix.version }}
-      - uses: actions/setup-go@v6
+      - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ^1.13.1
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: '9.x'
       - name: Assert best-effort artifact scan completed
@@ -94,7 +94,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Download all artifacts
-        uses: actions/download-artifact@v8
+        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
       - name: Check expected artifacts exist
         run: |
           LANGUAGES="cpp csharp go java javascript python"
diff --git .github/workflows/debug-artifacts-safe.yml .github/workflows/debug-artifacts-safe.yml
index 85b037cba6..4699436a11 100644
--- .github/workflows/debug-artifacts-safe.yml
+++ .github/workflows/debug-artifacts-safe.yml
@@ -49,17 +49,17 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Check out repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Prepare test
         id: prepare-test
         uses: ./.github/actions/prepare-test
         with:
           version: ${{ matrix.version }}
-      - uses: actions/setup-go@v6
+      - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
         with:
           go-version: ^1.13.1
       - name: Install .NET
-        uses: actions/setup-dotnet@v5
+        uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
         with:
           dotnet-version: '9.x'
       - name: Assert best-effort artifact scan completed
@@ -87,7 +87,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Download all artifacts
-        uses: actions/download-artifact@v8
+        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
       - name: Check expected artifacts exist
         run: |
           VERSIONS="stable-v2.20.3 default linked nightly-latest"
diff --git .github/workflows/post-release-mergeback.yml .github/workflows/post-release-mergeback.yml
index 7ba78e2295..313a1e3558 100644
--- .github/workflows/post-release-mergeback.yml
+++ .github/workflows/post-release-mergeback.yml
@@ -44,14 +44,14 @@ jobs:
           GITHUB_CONTEXT: '${{ toJson(github) }}'
         run: echo "${GITHUB_CONTEXT}"
 
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           fetch-depth: 0  # ensure we have all tags and can push commits
-      - uses: actions/setup-node@v6
+      - uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 24
           cache: 'npm'
-      - uses: actions/setup-python@v6
+      - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
         with:
           python-version: '3.12'
 
@@ -134,7 +134,7 @@ jobs:
           echo "::endgroup::"
 
       - name: Generate token
-        uses: actions/create-github-app-token@v3.2.0
+        uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
         id: app-token
         with:
           app-id: ${{ vars.AUTOMATION_APP_ID }}
diff --git .github/workflows/pr-checks.yml .github/workflows/pr-checks.yml
index 6b7656150d..195494c185 100644
--- .github/workflows/pr-checks.yml
+++ .github/workflows/pr-checks.yml
@@ -42,10 +42,10 @@ jobs:
         if: runner.os == 'Windows'
         run: git config --global core.autocrlf false
 
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
       - name: Set up Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: ${{ matrix.node-version }}
           cache: 'npm'
@@ -91,10 +91,10 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
       - name: Set up Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 24
           cache: 'npm'
@@ -155,7 +155,7 @@ jobs:
 
       - name: Upload repo size comment
         if: steps.fetch-base.outcome == 'success'
-        uses: actions/upload-artifact@v7
+        uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
         with:
           name: repo-size-comment
           path: ${{ runner.temp }}/repo-size/
@@ -164,7 +164,7 @@ jobs:
       - name: 'Backport: Check out base ref'
         id: checkout-base
         if: ${{ startsWith(github.head_ref, 'backport-') }}
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           ref: ${{ github.base_ref }}
 
@@ -203,7 +203,7 @@ jobs:
 
     steps:
       - name: Download repo size comment
-        uses: actions/download-artifact@v8
+        uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
         with:
           name: repo-size-comment
           path: repo-size-comment
diff --git .github/workflows/prepare-release.yml .github/workflows/prepare-release.yml
index fbddee3d52..915148e277 100644
--- .github/workflows/prepare-release.yml
+++ .github/workflows/prepare-release.yml
@@ -44,7 +44,7 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           fetch-depth: 0 # Need full history for calculation of diffs
 
diff --git .github/workflows/publish-immutable-action.yml .github/workflows/publish-immutable-action.yml
index e14bc30bc4..3944a81e6d 100644
--- .github/workflows/publish-immutable-action.yml
+++ .github/workflows/publish-immutable-action.yml
@@ -20,8 +20,8 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
       - name: Publish immutable release
         id: publish
-        uses: actions/publish-immutable-action@v0.0.4
+        uses: actions/publish-immutable-action@4bc8754ffc40f27910afb20287dbbbb675a4e978 # v0.0.4
diff --git .github/workflows/python312-windows.yml .github/workflows/python312-windows.yml
index 85901bff81..76a9c4ff26 100644
--- .github/workflows/python312-windows.yml
+++ .github/workflows/python312-windows.yml
@@ -35,11 +35,11 @@ jobs:
     runs-on: windows-latest
 
     steps:
-    - uses: actions/setup-python@v6
+    - uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
       with:
         python-version: 3.12
 
-    - uses: actions/checkout@v6
+    - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
     - name: Prepare test
       uses: ./.github/actions/prepare-test
diff --git .github/workflows/query-filters.yml .github/workflows/query-filters.yml
index b55ff8af27..3d1f4275cf 100644
--- .github/workflows/query-filters.yml
+++ .github/workflows/query-filters.yml
@@ -35,10 +35,10 @@ jobs:
       contents: read # This permission is needed to allow the GitHub Actions workflow to read the contents of the repository.
     steps:
     - name: Check out repository
-      uses: actions/checkout@v6
+      uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
     - name: Install Node.js
-      uses: actions/setup-node@v6
+      uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
       with:
         node-version: 24
         cache: npm
diff --git .github/workflows/rebuild.yml .github/workflows/rebuild.yml
index cafc432d98..f1d74dc8f4 100644
--- .github/workflows/rebuild.yml
+++ .github/workflows/rebuild.yml
@@ -24,13 +24,13 @@ jobs:
       pull-requests: write # needed to comment on the PR
     steps:
       - name: Checkout
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           fetch-depth: 0
           ref: ${{ env.HEAD_REF }}
 
       - name: Set up Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 24
           cache: 'npm'
diff --git .github/workflows/rollback-release.yml .github/workflows/rollback-release.yml
index ba10430f7d..e6a9da61f9 100644
--- .github/workflows/rollback-release.yml
+++ .github/workflows/rollback-release.yml
@@ -52,7 +52,7 @@ jobs:
 
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           fetch-depth: 0 # Need full history for calculation of diffs
 
@@ -136,7 +136,7 @@ jobs:
 
       - name: Generate token
         if: github.event_name == 'workflow_dispatch'
-        uses: actions/create-github-app-token@v3.2.0
+        uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
         id: app-token
         with:
           app-id: ${{ vars.AUTOMATION_APP_ID }}
diff --git .github/workflows/test-codeql-bundle-all.yml .github/workflows/test-codeql-bundle-all.yml
index 03ab6c37b3..c44dafc590 100644
--- .github/workflows/test-codeql-bundle-all.yml
+++ .github/workflows/test-codeql-bundle-all.yml
@@ -43,7 +43,7 @@ jobs:
     runs-on: ${{ matrix.os }}
     steps:
     - name: Check out repository
-      uses: actions/checkout@v6
+      uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
     - name: Prepare test
       id: prepare-test
       uses: ./.github/actions/prepare-test
@@ -51,7 +51,7 @@ jobs:
         version: ${{ matrix.version }}
         use-all-platform-bundle: true
     - name: Install .NET
-      uses: actions/setup-dotnet@v5
+      uses: actions/setup-dotnet@9a946fdbd5fb07b82b2f5a4466058b876ab72bb2 # v5.3.0
       with:
         dotnet-version: '9.x'
     - id: init
diff --git .github/workflows/update-bundle.yml .github/workflows/update-bundle.yml
index 837079481a..94c79bc56e 100644
--- .github/workflows/update-bundle.yml
+++ .github/workflows/update-bundle.yml
@@ -33,7 +33,7 @@ jobs:
           GITHUB_CONTEXT: '${{ toJson(github) }}'
         run: echo "$GITHUB_CONTEXT"
 
-      - uses: actions/checkout@v6
+      - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
 
       - name: Update git config
         run: |
@@ -41,12 +41,12 @@ jobs:
           git config --global user.name "github-actions[bot]"
 
       - name: Set up Python
-        uses: actions/setup-python@v6
+        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
         with:
           python-version: '3.12'
 
       - name: Set up Node.js
-        uses: actions/setup-node@v6
+        uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
         with:
           node-version: 24
           cache: 'npm'
diff --git .github/workflows/update-release-branch.yml .github/workflows/update-release-branch.yml
index 40d25e2163..bef7965742 100644
--- .github/workflows/update-release-branch.yml
+++ .github/workflows/update-release-branch.yml
@@ -38,7 +38,7 @@ jobs:
       contents: write # needed to push commits
       pull-requests: write # needed to create pull request
     steps:
-    - uses: actions/checkout@v6
+    - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       with:
         fetch-depth: 0  # Need full history for calculation of diffs
     - uses: ./.github/actions/release-initialise
@@ -94,14 +94,14 @@ jobs:
       pull-requests: write # needed to create pull request
     steps:
     - name: Generate token
-      uses: actions/create-github-app-token@v3.2.0
+      uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
       id: app-token
       with:
         app-id: ${{ vars.AUTOMATION_APP_ID }}
         private-key: ${{ secrets.AUTOMATION_PRIVATE_KEY }}
 
     - name: Checkout
-      uses: actions/checkout@v6
+      uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       with:
         fetch-depth: 0  # Need full history for calculation of diffs
         token: ${{ steps.app-token.outputs.token }}
diff --git .github/workflows/update-supported-enterprise-server-versions.yml .github/workflows/update-supported-enterprise-server-versions.yml
index 4cead58f4f..16f6f528c5 100644
--- .github/workflows/update-supported-enterprise-server-versions.yml
+++ .github/workflows/update-supported-enterprise-server-versions.yml
@@ -23,13 +23,13 @@ jobs:
 
     steps:
       - name: Setup Python
-        uses: actions/setup-python@v6
+        uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
         with:
           python-version: "3.13"
       - name: Checkout CodeQL Action
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
       - name: Checkout Enterprise Releases
-        uses: actions/checkout@v6
+        uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
         with:
           repository: github/enterprise-releases
           token: ${{ secrets.ENTERPRISE_RELEASE_TOKEN }}
diff --git CHANGELOG.md CHANGELOG.md
index a46c659fc0..a16b469fad 100644
--- CHANGELOG.md
+++ CHANGELOG.md
@@ -2,6 +2,16 @@
 
 See the [releases page](https://github.com/github/codeql-action/releases) for the relevant changes to the CodeQL CLI and language packs.
 
+## 4.36.2 - 04 Jun 2026
+
+ - Cache CodeQL CLI version information across Actions steps. [#3943](https://github.com/github/codeql-action/pull/3943)
+ - Reduce requests while waiting for analysis processing by using exponential backoff when polling SARIF processing status. [#3937](https://github.com/github/codeql-action/pull/3937)
+- Update default CodeQL bundle version to [2.25.6](https://github.com/github/codeql-action/releases/tag/codeql-bundle-v2.25.6). [#3948](https://github.com/github/codeql-action/pull/3948)
+
+## 4.36.1 - 02 Jun 2026
+
+No user facing changes.
+
 ## 4.36.0 - 22 May 2026
 
 - _Breaking change_: Bump the minimum required CodeQL bundle version to 2.19.4. [#3894](https://github.com/github/codeql-action/pull/3894)
diff --git lib/defaults.json lib/defaults.json
index a57ede64b9..7c82ff2a6e 100644
--- lib/defaults.json
+++ lib/defaults.json
@@ -1,6 +1,6 @@
 {
-  "bundleVersion": "codeql-bundle-v2.25.5",
-  "cliVersion": "2.25.5",
-  "priorBundleVersion": "codeql-bundle-v2.25.4",
-  "priorCliVersion": "2.25.4"
+  "bundleVersion": "codeql-bundle-v2.25.6",
+  "cliVersion": "2.25.6",
+  "priorBundleVersion": "codeql-bundle-v2.25.5",
+  "priorCliVersion": "2.25.5"
 }
diff --git lib/entry-points.js lib/entry-points.js
index 75cfa8cbb4..0e93e0ec61 100644
--- lib/entry-points.js
+++ lib/entry-points.js
@@ -19179,12 +19179,12 @@ var require_lib = __commonJS({
             throw new Error("Client has already been disposed.");
           }
           const parsedUrl = new URL(requestUrl);
-          let info7 = this._prepareRequest(verb, parsedUrl, headers);
+          let info8 = this._prepareRequest(verb, parsedUrl, headers);
           const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
           let numTries = 0;
           let response;
           do {
-            response = yield this.requestRaw(info7, data);
+            response = yield this.requestRaw(info8, data);
             if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
               let authenticationHandler;
               for (const handler2 of this.handlers) {
@@ -19194,7 +19194,7 @@ var require_lib = __commonJS({
                 }
               }
               if (authenticationHandler) {
-                return authenticationHandler.handleAuthentication(this, info7, data);
+                return authenticationHandler.handleAuthentication(this, info8, data);
               } else {
                 return response;
               }
@@ -19217,8 +19217,8 @@ var require_lib = __commonJS({
                   }
                 }
               }
-              info7 = this._prepareRequest(verb, parsedRedirectUrl, headers);
-              response = yield this.requestRaw(info7, data);
+              info8 = this._prepareRequest(verb, parsedRedirectUrl, headers);
+              response = yield this.requestRaw(info8, data);
               redirectsRemaining--;
             }
             if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -19247,7 +19247,7 @@ var require_lib = __commonJS({
        * @param info
        * @param data
        */
-      requestRaw(info7, data) {
+      requestRaw(info8, data) {
         return __awaiter2(this, void 0, void 0, function* () {
           return new Promise((resolve13, reject) => {
             function callbackForResult(err, res) {
@@ -19259,7 +19259,7 @@ var require_lib = __commonJS({
                 resolve13(res);
               }
             }
-            this.requestRawWithCallback(info7, data, callbackForResult);
+            this.requestRawWithCallback(info8, data, callbackForResult);
           });
         });
       }
@@ -19269,12 +19269,12 @@ var require_lib = __commonJS({
        * @param data
        * @param onResult
        */
-      requestRawWithCallback(info7, data, onResult) {
+      requestRawWithCallback(info8, data, onResult) {
         if (typeof data === "string") {
-          if (!info7.options.headers) {
-            info7.options.headers = {};
+          if (!info8.options.headers) {
+            info8.options.headers = {};
           }
-          info7.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
+          info8.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
         }
         let callbackCalled = false;
         function handleResult(err, res) {
@@ -19283,7 +19283,7 @@ var require_lib = __commonJS({
             onResult(err, res);
           }
         }
-        const req = info7.httpModule.request(info7.options, (msg) => {
+        const req = info8.httpModule.request(info8.options, (msg) => {
           const res = new HttpClientResponse(msg);
           handleResult(void 0, res);
         });
@@ -19295,7 +19295,7 @@ var require_lib = __commonJS({
           if (socket) {
             socket.end();
           }
-          handleResult(new Error(`Request timeout: ${info7.options.path}`));
+          handleResult(new Error(`Request timeout: ${info8.options.path}`));
         });
         req.on("error", function(err) {
           handleResult(err);
@@ -19331,27 +19331,27 @@ var require_lib = __commonJS({
         return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
       }
       _prepareRequest(method, requestUrl, headers) {
-        const info7 = {};
-        info7.parsedUrl = requestUrl;
-        const usingSsl = info7.parsedUrl.protocol === "https:";
-        info7.httpModule = usingSsl ? https3 : http;
+        const info8 = {};
+        info8.parsedUrl = requestUrl;
+        const usingSsl = info8.parsedUrl.protocol === "https:";
+        info8.httpModule = usingSsl ? https3 : http;
         const defaultPort = usingSsl ? 443 : 80;
-        info7.options = {};
-        info7.options.host = info7.parsedUrl.hostname;
-        info7.options.port = info7.parsedUrl.port ? parseInt(info7.parsedUrl.port) : defaultPort;
-        info7.options.path = (info7.parsedUrl.pathname || "") + (info7.parsedUrl.search || "");
-        info7.options.method = method;
-        info7.options.headers = this._mergeHeaders(headers);
+        info8.options = {};
+        info8.options.host = info8.parsedUrl.hostname;
+        info8.options.port = info8.parsedUrl.port ? parseInt(info8.parsedUrl.port) : defaultPort;
+        info8.options.path = (info8.parsedUrl.pathname || "") + (info8.parsedUrl.search || "");
+        info8.options.method = method;
+        info8.options.headers = this._mergeHeaders(headers);
         if (this.userAgent != null) {
-          info7.options.headers["user-agent"] = this.userAgent;
+          info8.options.headers["user-agent"] = this.userAgent;
         }
-        info7.options.agent = this._getAgent(info7.parsedUrl);
+        info8.options.agent = this._getAgent(info8.parsedUrl);
         if (this.handlers) {
           for (const handler2 of this.handlers) {
-            handler2.prepareRequest(info7.options);
+            handler2.prepareRequest(info8.options);
           }
         }
-        return info7;
+        return info8;
       }
       _mergeHeaders(headers) {
         if (this.requestOptions && this.requestOptions.headers) {
@@ -21406,7 +21406,7 @@ var require_core = __commonJS({
     exports2.error = error3;
     exports2.warning = warning14;
     exports2.notice = notice;
-    exports2.info = info7;
+    exports2.info = info8;
     exports2.startGroup = startGroup4;
     exports2.endGroup = endGroup4;
     exports2.group = group;
@@ -21503,7 +21503,7 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
     function notice(message, properties = {}) {
       (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
     }
-    function info7(message) {
+    function info8(message) {
       process.stdout.write(message + os7.EOL);
     }
     function startGroup4(name) {
@@ -26704,6 +26704,47 @@ var require_coerce = __commonJS({
   }
 });
 
+// node_modules/semver/functions/truncate.js
+var require_truncate = __commonJS({
+  "node_modules/semver/functions/truncate.js"(exports2, module2) {
+    "use strict";
+    var parse2 = require_parse2();
+    var constants = require_constants6();
+    var SemVer = require_semver();
+    var truncate = (version, truncation, options) => {
+      if (!constants.RELEASE_TYPES.includes(truncation)) {
+        return null;
+      }
+      const clonedVersion = cloneInputVersion(version, options);
+      return clonedVersion && doTruncation(clonedVersion, truncation);
+    };
+    var cloneInputVersion = (version, options) => {
+      const versionStringToParse = version instanceof SemVer ? version.version : version;
+      return parse2(versionStringToParse, options);
+    };
+    var doTruncation = (version, truncation) => {
+      if (isPrerelease(truncation)) {
+        return version.version;
+      }
+      version.prerelease = [];
+      switch (truncation) {
+        case "major":
+          version.minor = 0;
+          version.patch = 0;
+          break;
+        case "minor":
+          version.patch = 0;
+          break;
+      }
+      return version.format();
+    };
+    var isPrerelease = (type2) => {
+      return type2.startsWith("pre");
+    };
+    module2.exports = truncate;
+  }
+});
+
 // node_modules/semver/internal/lrucache.js
 var require_lrucache = __commonJS({
   "node_modules/semver/internal/lrucache.js"(exports2, module2) {
@@ -26812,6 +26853,7 @@ var require_range = __commonJS({
         return this.range;
       }
       parseRange(range) {
+        range = range.replace(BUILDSTRIPRE, "");
         const memoOpts = (this.options.includePrerelease && FLAG_INCLUDE_PRERELEASE) | (this.options.loose && FLAG_LOOSE);
         const memoKey = memoOpts + ":" + range;
         const cached = cache.get(memoKey);
@@ -26894,12 +26936,14 @@ var require_range = __commonJS({
     var SemVer = require_semver();
     var {
       safeRe: re,
+      src,
       t,
       comparatorTrimReplace,
       tildeTrimReplace,
       caretTrimReplace
     } = require_re();
     var { FLAG_INCLUDE_PRERELEASE, FLAG_LOOSE } = require_constants6();
+    var BUILDSTRIPRE = new RegExp(src[t.BUILD], "g");
     var isNullSet = (c) => c.value === "<0.0.0-0";
     var isAny = (c) => c.value === "";
     var isSatisfiable = (comparators, options) => {
@@ -27655,7 +27699,7 @@ var require_subset = __commonJS({
             if (higher === c && higher !== gt) {
               return false;
             }
-          } else if (gt.operator === ">=" && !satisfies2(gt.semver, String(c), options)) {
+          } else if (gt.operator === ">=" && !c.test(gt.semver)) {
             return false;
           }
         }
@@ -27670,7 +27714,7 @@ var require_subset = __commonJS({
             if (lower === c && lower !== lt2) {
               return false;
             }
-          } else if (lt2.operator === "<=" && !satisfies2(lt2.semver, String(c), options)) {
+          } else if (lt2.operator === "<=" && !c.test(lt2.semver)) {
             return false;
           }
         }
@@ -27738,6 +27782,7 @@ var require_semver2 = __commonJS({
     var lte = require_lte();
     var cmp = require_cmp();
     var coerce3 = require_coerce();
+    var truncate = require_truncate();
     var Comparator = require_comparator();
     var Range2 = require_range();
     var satisfies2 = require_satisfies();
@@ -27776,6 +27821,7 @@ var require_semver2 = __commonJS({
       lte,
       cmp,
       coerce: coerce3,
+      truncate,
       Comparator,
       Range: Range2,
       satisfies: satisfies2,
@@ -42359,12 +42405,12 @@ var require_operationHelpers = __commonJS({
       if (hasOriginalRequest(request3)) {
         return getOperationRequestInfo(request3[originalRequestSymbol]);
       }
-      let info7 = state_js_1.state.operationRequestMap.get(request3);
-      if (!info7) {
-        info7 = {};
-        state_js_1.state.operationRequestMap.set(request3, info7);
+      let info8 = state_js_1.state.operationRequestMap.get(request3);
+      if (!info8) {
+        info8 = {};
+        state_js_1.state.operationRequestMap.set(request3, info8);
       }
-      return info7;
+      return info8;
     }
   }
 });
@@ -76911,9 +76957,9 @@ var require_reflection_type_check = __commonJS({
     var reflection_info_1 = require_reflection_info();
     var oneof_1 = require_oneof();
     var ReflectionTypeCheck = class {
-      constructor(info7) {
+      constructor(info8) {
         var _a;
-        this.fields = (_a = info7.fields) !== null && _a !== void 0 ? _a : [];
+        this.fields = (_a = info8.fields) !== null && _a !== void 0 ? _a : [];
       }
       prepare() {
         if (this.data)
@@ -77159,8 +77205,8 @@ var require_reflection_json_reader = __commonJS({
     var assert_1 = require_assert();
     var reflection_long_convert_1 = require_reflection_long_convert();
     var ReflectionJsonReader = class {
-      constructor(info7) {
-        this.info = info7;
+      constructor(info8) {
+        this.info = info8;
       }
       prepare() {
         var _a;
@@ -77456,9 +77502,9 @@ var require_reflection_json_writer = __commonJS({
     var reflection_info_1 = require_reflection_info();
     var assert_1 = require_assert();
     var ReflectionJsonWriter = class {
-      constructor(info7) {
+      constructor(info8) {
         var _a;
-        this.fields = (_a = info7.fields) !== null && _a !== void 0 ? _a : [];
+        this.fields = (_a = info8.fields) !== null && _a !== void 0 ? _a : [];
       }
       /**
        * Converts the message to a JSON object, based on the field descriptors.
@@ -77711,8 +77757,8 @@ var require_reflection_binary_reader = __commonJS({
     var reflection_long_convert_1 = require_reflection_long_convert();
     var reflection_scalar_default_1 = require_reflection_scalar_default();
     var ReflectionBinaryReader = class {
-      constructor(info7) {
-        this.info = info7;
+      constructor(info8) {
+        this.info = info8;
       }
       prepare() {
         var _a;
@@ -77885,8 +77931,8 @@ var require_reflection_binary_writer = __commonJS({
     var assert_1 = require_assert();
     var pb_long_1 = require_pb_long();
     var ReflectionBinaryWriter = class {
-      constructor(info7) {
-        this.info = info7;
+      constructor(info8) {
+        this.info = info8;
       }
       prepare() {
         if (!this.fields) {
@@ -78136,9 +78182,9 @@ var require_reflection_merge_partial = __commonJS({
     "use strict";
     Object.defineProperty(exports2, "__esModule", { value: true });
     exports2.reflectionMergePartial = void 0;
-    function reflectionMergePartial(info7, target, source) {
+    function reflectionMergePartial(info8, target, source) {
       let fieldValue, input = source, output;
-      for (let field of info7.fields) {
+      for (let field of info8.fields) {
         let name = field.localName;
         if (field.oneof) {
           const group = input[field.oneof];
@@ -78207,12 +78253,12 @@ var require_reflection_equals = __commonJS({
     Object.defineProperty(exports2, "__esModule", { value: true });
     exports2.reflectionEquals = void 0;
     var reflection_info_1 = require_reflection_info();
-    function reflectionEquals(info7, a, b) {
+    function reflectionEquals(info8, a, b) {
       if (a === b)
         return true;
       if (!a || !b)
         return false;
-      for (let field of info7.fields) {
+      for (let field of info8.fields) {
         let localName = field.localName;
         let val_a = field.oneof ? a[field.oneof][localName] : a[localName];
         let val_b = field.oneof ? b[field.oneof][localName] : b[localName];
@@ -91232,7 +91278,7 @@ var require_async = __commonJS({
         }
       }
       var sortBy$1 = awaitify(sortBy, 3);
-      function timeout(asyncFn, milliseconds, info7) {
+      function timeout(asyncFn, milliseconds, info8) {
         var fn = wrapAsync(asyncFn);
         return initialParams((args, callback) => {
           var timedOut = false;
@@ -91241,8 +91287,8 @@ var require_async = __commonJS({
             var name = asyncFn.name || "anonymous";
             var error3 = new Error('Callback function "' + name + '" timed out.');
             error3.code = "ETIMEDOUT";
-            if (info7) {
-              error3.info = info7;
+            if (info8) {
+              error3.info = info8;
             }
             timedOut = true;
             callback(error3);
@@ -114638,12 +114684,12 @@ var require_lib4 = __commonJS({
             throw new Error("Client has already been disposed.");
           }
           const parsedUrl = new URL(requestUrl);
-          let info7 = this._prepareRequest(verb, parsedUrl, headers);
+          let info8 = this._prepareRequest(verb, parsedUrl, headers);
           const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
           let numTries = 0;
           let response;
           do {
-            response = yield this.requestRaw(info7, data);
+            response = yield this.requestRaw(info8, data);
             if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
               let authenticationHandler;
               for (const handler2 of this.handlers) {
@@ -114653,7 +114699,7 @@ var require_lib4 = __commonJS({
                 }
               }
               if (authenticationHandler) {
-                return authenticationHandler.handleAuthentication(this, info7, data);
+                return authenticationHandler.handleAuthentication(this, info8, data);
               } else {
                 return response;
               }
@@ -114676,8 +114722,8 @@ var require_lib4 = __commonJS({
                   }
                 }
               }
-              info7 = this._prepareRequest(verb, parsedRedirectUrl, headers);
-              response = yield this.requestRaw(info7, data);
+              info8 = this._prepareRequest(verb, parsedRedirectUrl, headers);
+              response = yield this.requestRaw(info8, data);
               redirectsRemaining--;
             }
             if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -114706,7 +114752,7 @@ var require_lib4 = __commonJS({
        * @param info
        * @param data
        */
-      requestRaw(info7, data) {
+      requestRaw(info8, data) {
         return __awaiter2(this, void 0, void 0, function* () {
           return new Promise((resolve13, reject) => {
             function callbackForResult(err, res) {
@@ -114718,7 +114764,7 @@ var require_lib4 = __commonJS({
                 resolve13(res);
               }
             }
-            this.requestRawWithCallback(info7, data, callbackForResult);
+            this.requestRawWithCallback(info8, data, callbackForResult);
           });
         });
       }
@@ -114728,12 +114774,12 @@ var require_lib4 = __commonJS({
        * @param data
        * @param onResult
        */
-      requestRawWithCallback(info7, data, onResult) {
+      requestRawWithCallback(info8, data, onResult) {
         if (typeof data === "string") {
-          if (!info7.options.headers) {
-            info7.options.headers = {};
+          if (!info8.options.headers) {
+            info8.options.headers = {};
           }
-          info7.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
+          info8.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
         }
         let callbackCalled = false;
         function handleResult(err, res) {
@@ -114742,7 +114788,7 @@ var require_lib4 = __commonJS({
             onResult(err, res);
           }
         }
-        const req = info7.httpModule.request(info7.options, (msg) => {
+        const req = info8.httpModule.request(info8.options, (msg) => {
           const res = new HttpClientResponse(msg);
           handleResult(void 0, res);
         });
@@ -114754,7 +114800,7 @@ var require_lib4 = __commonJS({
           if (socket) {
             socket.end();
           }
-          handleResult(new Error(`Request timeout: ${info7.options.path}`));
+          handleResult(new Error(`Request timeout: ${info8.options.path}`));
         });
         req.on("error", function(err) {
           handleResult(err);
@@ -114790,27 +114836,27 @@ var require_lib4 = __commonJS({
         return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
       }
       _prepareRequest(method, requestUrl, headers) {
-        const info7 = {};
-        info7.parsedUrl = requestUrl;
-        const usingSsl = info7.parsedUrl.protocol === "https:";
-        info7.httpModule = usingSsl ? https3 : http;
+        const info8 = {};
+        info8.parsedUrl = requestUrl;
+        const usingSsl = info8.parsedUrl.protocol === "https:";
+        info8.httpModule = usingSsl ? https3 : http;
         const defaultPort = usingSsl ? 443 : 80;
-        info7.options = {};
-        info7.options.host = info7.parsedUrl.hostname;
-        info7.options.port = info7.parsedUrl.port ? parseInt(info7.parsedUrl.port) : defaultPort;
-        info7.options.path = (info7.parsedUrl.pathname || "") + (info7.parsedUrl.search || "");
-        info7.options.method = method;
-        info7.options.headers = this._mergeHeaders(headers);
+        info8.options = {};
+        info8.options.host = info8.parsedUrl.hostname;
+        info8.options.port = info8.parsedUrl.port ? parseInt(info8.parsedUrl.port) : defaultPort;
+        info8.options.path = (info8.parsedUrl.pathname || "") + (info8.parsedUrl.search || "");
+        info8.options.method = method;
+        info8.options.headers = this._mergeHeaders(headers);
         if (this.userAgent != null) {
-          info7.options.headers["user-agent"] = this.userAgent;
+          info8.options.headers["user-agent"] = this.userAgent;
         }
-        info7.options.agent = this._getAgent(info7.parsedUrl);
+        info8.options.agent = this._getAgent(info8.parsedUrl);
         if (this.handlers) {
           for (const handler2 of this.handlers) {
-            handler2.prepareRequest(info7.options);
+            handler2.prepareRequest(info8.options);
           }
         }
-        return info7;
+        return info8;
       }
       _mergeHeaders(headers) {
         if (this.requestOptions && this.requestOptions.headers) {
@@ -121198,11 +121244,11 @@ var require_dist_node12 = __commonJS({
     }
     async function wrapRequest2(state, request3, options) {
       const limiter = new Bottleneck2();
-      limiter.on("failed", function(error3, info7) {
+      limiter.on("failed", function(error3, info8) {
         const maxRetries = ~~error3.request.request.retries;
         const after = ~~error3.request.request.retryAfter;
-        options.request.retryCount = info7.retryCount + 1;
-        if (maxRetries > info7.retryCount) {
+        options.request.retryCount = info8.retryCount + 1;
+        if (maxRetries > info8.retryCount) {
           return after * state.retryAfterBaseValue;
         }
       });
@@ -122410,12 +122456,12 @@ var require_lib5 = __commonJS({
             throw new Error("Client has already been disposed.");
           }
           const parsedUrl = new URL(requestUrl);
-          let info7 = this._prepareRequest(verb, parsedUrl, headers);
+          let info8 = this._prepareRequest(verb, parsedUrl, headers);
           const maxTries = this._allowRetries && RetryableHttpVerbs.includes(verb) ? this._maxRetries + 1 : 1;
           let numTries = 0;
           let response;
           do {
-            response = yield this.requestRaw(info7, data);
+            response = yield this.requestRaw(info8, data);
             if (response && response.message && response.message.statusCode === HttpCodes.Unauthorized) {
               let authenticationHandler;
               for (const handler2 of this.handlers) {
@@ -122425,7 +122471,7 @@ var require_lib5 = __commonJS({
                 }
               }
               if (authenticationHandler) {
-                return authenticationHandler.handleAuthentication(this, info7, data);
+                return authenticationHandler.handleAuthentication(this, info8, data);
               } else {
                 return response;
               }
@@ -122448,8 +122494,8 @@ var require_lib5 = __commonJS({
                   }
                 }
               }
-              info7 = this._prepareRequest(verb, parsedRedirectUrl, headers);
-              response = yield this.requestRaw(info7, data);
+              info8 = this._prepareRequest(verb, parsedRedirectUrl, headers);
+              response = yield this.requestRaw(info8, data);
               redirectsRemaining--;
             }
             if (!response.message.statusCode || !HttpResponseRetryCodes.includes(response.message.statusCode)) {
@@ -122478,7 +122524,7 @@ var require_lib5 = __commonJS({
        * @param info
        * @param data
        */
-      requestRaw(info7, data) {
+      requestRaw(info8, data) {
         return __awaiter2(this, void 0, void 0, function* () {
           return new Promise((resolve13, reject) => {
             function callbackForResult(err, res) {
@@ -122490,7 +122536,7 @@ var require_lib5 = __commonJS({
                 resolve13(res);
               }
             }
-            this.requestRawWithCallback(info7, data, callbackForResult);
+            this.requestRawWithCallback(info8, data, callbackForResult);
           });
         });
       }
@@ -122500,12 +122546,12 @@ var require_lib5 = __commonJS({
        * @param data
        * @param onResult
        */
-      requestRawWithCallback(info7, data, onResult) {
+      requestRawWithCallback(info8, data, onResult) {
         if (typeof data === "string") {
-          if (!info7.options.headers) {
-            info7.options.headers = {};
+          if (!info8.options.headers) {
+            info8.options.headers = {};
           }
-          info7.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
+          info8.options.headers["Content-Length"] = Buffer.byteLength(data, "utf8");
         }
         let callbackCalled = false;
         function handleResult(err, res) {
@@ -122514,7 +122560,7 @@ var require_lib5 = __commonJS({
             onResult(err, res);
           }
         }
-        const req = info7.httpModule.request(info7.options, (msg) => {
+        const req = info8.httpModule.request(info8.options, (msg) => {
           const res = new HttpClientResponse(msg);
           handleResult(void 0, res);
         });
@@ -122526,7 +122572,7 @@ var require_lib5 = __commonJS({
           if (socket) {
             socket.end();
           }
-          handleResult(new Error(`Request timeout: ${info7.options.path}`));
+          handleResult(new Error(`Request timeout: ${info8.options.path}`));
         });
         req.on("error", function(err) {
           handleResult(err);
@@ -122562,27 +122608,27 @@ var require_lib5 = __commonJS({
         return this._getProxyAgentDispatcher(parsedUrl, proxyUrl);
       }
       _prepareRequest(method, requestUrl, headers) {
-        const info7 = {};
-        info7.parsedUrl = requestUrl;
-        const usingSsl = info7.parsedUrl.protocol === "https:";
-        info7.httpModule = usingSsl ? https3 : http;
+        const info8 = {};
+        info8.parsedUrl = requestUrl;
+        const usingSsl = info8.parsedUrl.protocol === "https:";
+        info8.httpModule = usingSsl ? https3 : http;
         const defaultPort = usingSsl ? 443 : 80;
-        info7.options = {};
-        info7.options.host = info7.parsedUrl.hostname;
-        info7.options.port = info7.parsedUrl.port ? parseInt(info7.parsedUrl.port) : defaultPort;
-        info7.options.path = (info7.parsedUrl.pathname || "") + (info7.parsedUrl.search || "");
-        info7.options.method = method;
-        info7.options.headers = this._mergeHeaders(headers);
+        info8.options = {};
+        info8.options.host = info8.parsedUrl.hostname;
+        info8.options.port = info8.parsedUrl.port ? parseInt(info8.parsedUrl.port) : defaultPort;
+        info8.options.path = (info8.parsedUrl.pathname || "") + (info8.parsedUrl.search || "");
+        info8.options.method = method;
+        info8.options.headers = this._mergeHeaders(headers);
         if (this.userAgent != null) {
-          info7.options.headers["user-agent"] = this.userAgent;
+          info8.options.headers["user-agent"] = this.userAgent;
         }
-        info7.options.agent = this._getAgent(info7.parsedUrl);
+        info8.options.agent = this._getAgent(info8.parsedUrl);
         if (this.handlers) {
           for (const handler2 of this.handlers) {
-            handler2.prepareRequest(info7.options);
+            handler2.prepareRequest(info8.options);
           }
         }
-        return info7;
+        return info8;
       }
       _mergeHeaders(headers) {
         if (this.requestOptions && this.requestOptions.headers) {
@@ -124572,10 +124618,10 @@ Support boolean input list: \`true | True | TRUE | false | False | FALSE\``);
       (0, command_1.issueCommand)("notice", (0, utils_1.toCommandProperties)(properties), message instanceof Error ? message.toString() : message);
     }
     exports2.notice = notice;
-    function info7(message) {
+    function info8(message) {
       process.stdout.write(message + os7.EOL);
     }
-    exports2.info = info7;
+    exports2.info = info8;
     function startGroup4(name) {
       (0, command_1.issue)("group", name);
     }
@@ -124988,7 +125034,7 @@ var require_tmp = __commonJS({
             cb(null, path28.join(parentDir, path28.basename(pathToResolve)));
           });
         } else {
-          fs30.realpath(path28, cb);
+          fs30.realpath(pathToResolve, cb);
         }
       });
     }
@@ -125020,16 +125066,31 @@ var require_tmp = __commonJS({
       ].join("");
       return path28.join(tmpDir, opts.dir, name);
     }
+    function _assertPath(option, value) {
+      if (typeof value !== "string") {
+        throw new Error(`${option} option must be a string, got "${typeof value}".`);
+      }
+      if (value.includes("..")) {
+        throw new Error("Relative value not allowed");
+      }
+      return value;
+    }
     function _assertOptionsBase(options) {
       if (!_isUndefined(options.name)) {
         const name = options.name;
         if (path28.isAbsolute(name)) throw new Error(`name option must not contain an absolute path, found "${name}".`);
         const basename2 = path28.basename(name);
-        if (basename2 === ".." || basename2 === "." || basename2 !== name)
+        if (basename2 === ".." || basename2 === "." || basename2 !== name) {
           throw new Error(`name option must not contain a path, found "${name}".`);
+        }
       }
-      if (!_isUndefined(options.template) && !options.template.match(TEMPLATE_PATTERN)) {
-        throw new Error(`Invalid template, found "${options.template}".`);
+      if (!_isUndefined(options.template)) {
+        if (typeof options.template !== "string") {
+          throw new Error(`template option must be a string, got "${typeof options.template}".`);
+        }
+        if (!options.template.match(TEMPLATE_PATTERN)) {
+          throw new Error(`Invalid template, found "${options.template}".`);
+        }
       }
       if (!_isUndefined(options.tries) && isNaN(options.tries) || options.tries < 0) {
         throw new Error(`Invalid tries, found "${options.tries}".`);
@@ -125039,15 +125100,16 @@ var require_tmp = __commonJS({
       options.detachDescriptor = !!options.detachDescriptor;
       options.discardDescriptor = !!options.discardDescriptor;
       options.unsafeCleanup = !!options.unsafeCleanup;
-      options.prefix = _isUndefined(options.prefix) ? "" : options.prefix;
-      options.postfix = _isUndefined(options.postfix) ? "" : options.postfix;
+      options.prefix = _isUndefined(options.prefix) ? "" : _assertPath("prefix", options.prefix);
+      options.postfix = _isUndefined(options.postfix) ? "" : _assertPath("postfix", options.postfix);
+      options.template = _isUndefined(options.template) ? void 0 : _assertPath("template", options.template);
     }
     function _getRelativePath(option, name, tmpDir, cb) {
       if (_isUndefined(name)) return cb(null);
       _resolvePath(name, tmpDir, function(err, resolvedPath) {
         if (err) return cb(err);
         const relativePath = path28.relative(tmpDir, resolvedPath);
-        if (!resolvedPath.startsWith(tmpDir)) {
+        if (relativePath.startsWith("..") || path28.isAbsolute(relativePath)) {
           return cb(new Error(`${option} option must be relative to "${tmpDir}", found "${relativePath}".`));
         }
         cb(null, relativePath);
@@ -125057,7 +125119,7 @@ var require_tmp = __commonJS({
       if (_isUndefined(name)) return;
       const resolvedPath = _resolvePathSync(name, tmpDir);
       const relativePath = path28.relative(tmpDir, resolvedPath);
-      if (!resolvedPath.startsWith(tmpDir)) {
+      if (relativePath.startsWith("..") || path28.isAbsolute(relativePath)) {
         throw new Error(`${option} option must be relative to "${tmpDir}", found "${relativePath}".`);
       }
       return relativePath;
@@ -147623,7 +147685,7 @@ var safeDump = renamed("safeDump", "dump");
 var semver = __toESM(require_semver2());
 
 // src/api-compatibility.json
-var maximumVersion = "3.21";
+var maximumVersion = "3.22";
 var minimumVersion = "3.16";
 
 // src/json/index.ts
@@ -148003,13 +148065,42 @@ function asHTTPError(arg) {
   return void 0;
 }
 var cachedCodeQlVersion = void 0;
-function cacheCodeQlVersion(version) {
+function isVersionInfo(x) {
+  const candidate = x;
+  return typeof candidate === "object" && candidate !== null && typeof candidate.version === "string" && (candidate.features === void 0 || typeof candidate.features === "object" && candidate.features !== null) && (candidate.overlayVersion === void 0 || typeof candidate.overlayVersion === "number");
+}
+function isPersistedVersionInfo(x) {
+  const candidate = x;
+  return typeof candidate === "object" && candidate !== null && typeof candidate.cmd === "string" && isVersionInfo(candidate.version);
+}
+function cacheCodeQlVersion(cmd, version) {
   if (cachedCodeQlVersion !== void 0) {
     throw new Error("cacheCodeQlVersion() should be called only once");
   }
   cachedCodeQlVersion = version;
+  core3.exportVariable(
+    "CODEQL_ACTION_CLI_VERSION_INFO" /* CODEQL_VERSION_INFO */,
+    JSON.stringify({ cmd, version })
+  );
 }
-function getCachedCodeQlVersion() {
+function getCachedCodeQlVersion(cmd) {
+  if (cachedCodeQlVersion !== void 0) {
+    return cachedCodeQlVersion;
+  }
+  const serialized = process.env["CODEQL_ACTION_CLI_VERSION_INFO" /* CODEQL_VERSION_INFO */];
+  if (!serialized) {
+    return void 0;
+  }
+  let persisted;
+  try {
+    persisted = JSON.parse(serialized);
+  } catch {
+    return void 0;
+  }
+  if (!isPersistedVersionInfo(persisted) || cmd !== void 0 && persisted.cmd !== cmd) {
+    return void 0;
+  }
+  cachedCodeQlVersion = persisted.version;
   return cachedCodeQlVersion;
 }
 async function codeQlVersionAtLeast(codeql, requiredVersion) {
@@ -148307,7 +148398,7 @@ function getDiffRangesJsonFilePath() {
   return path2.join(getTemporaryDirectory(), PR_DIFF_RANGE_JSON_FILENAME);
 }
 function getActionVersion() {
-  return "4.36.0";
+  return "4.36.2";
 }
 function getWorkflowEventName() {
   return getRequiredEnvParam("GITHUB_EVENT_NAME");
@@ -148610,11 +148701,11 @@ async function errorRequest(state, octokit, error3, options) {
 }
 async function wrapRequest(state, octokit, request3, options) {
   const limiter = new import_light.default();
-  limiter.on("failed", function(error3, info7) {
+  limiter.on("failed", function(error3, info8) {
     const maxRetries = ~~error3.request.request?.retries;
     const after = ~~error3.request.request?.retryAfter;
-    options.request.retryCount = info7.retryCount + 1;
-    if (maxRetries > info7.retryCount) {
+    options.request.retryCount = info8.retryCount + 1;
+    if (maxRetries > info8.retryCount) {
       return after * state.retryAfterBaseValue;
     }
   });
@@ -148871,8 +148962,8 @@ function wrapApiConfigurationError(e) {
 }
 
 // src/defaults.json
-var bundleVersion = "codeql-bundle-v2.25.5";
-var cliVersion = "2.25.5";
+var bundleVersion = "codeql-bundle-v2.25.6";
+var cliVersion = "2.25.6";
 
 // src/overlay/index.ts
 var fs4 = __toESM(require("fs"));
@@ -149337,6 +149428,11 @@ var featureConfig = {
     legacyApi: true,
     minimumVersion: void 0
   },
+  ["force_jgit" /* ForceJGit */]: {
+    defaultValue: false,
+    envVar: "CODEQL_ACTION_FORCE_JGIT",
+    minimumVersion: void 0
+  },
   ["force_nightly" /* ForceNightly */]: {
     defaultValue: false,
     envVar: "CODEQL_ACTION_FORCE_NIGHTLY",
@@ -151652,6 +151748,7 @@ async function initActionState({
     extraQueryExclusions: [],
     overlayDatabaseMode: "none" /* None */,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: false,
     repositoryProperties,
     enableFileCoverageInformation
   };
@@ -151780,6 +151877,7 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
     return validateOverlayDatabaseMode(
       modeEnv,
       false,
+      true,
       codeql,
       languages,
       sourceRoot,
@@ -151854,6 +151952,7 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
   return validateOverlayDatabaseMode(
     overlayDatabaseMode,
     true,
+    false,
     codeql,
     languages,
     sourceRoot,
@@ -151862,7 +151961,7 @@ async function checkOverlayEnablement(codeql, features, languages, sourceRoot, b
     logger
   );
 }
-async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, codeql, languages, sourceRoot, buildMode, gitVersion, logger) {
+async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDatabaseCaching, overlayModeSetExplicitly, codeql, languages, sourceRoot, buildMode, gitVersion, logger) {
   if (buildMode !== "none" /* None */ && (await Promise.all(
     languages.map(
       async (l) => l !== "go" /* go */ && // Workaround to allow overlay analysis for Go with any build
@@ -151906,7 +152005,8 @@ async function validateOverlayDatabaseMode(overlayDatabaseMode, useOverlayDataba
   }
   return new Success({
     overlayDatabaseMode,
-    useOverlayDatabaseCaching
+    useOverlayDatabaseCaching,
+    overlayModeSetExplicitly
   });
 }
 async function isTrapCachingEnabled(features, overlayDatabaseMode) {
@@ -151944,7 +152044,7 @@ function hasQueryCustomisation(userConfig) {
   return isDefined2(userConfig["disable-default-queries"]) || isDefined2(userConfig.queries) || isDefined2(userConfig["query-filters"]);
 }
 async function applyIncrementalAnalysisSettings(config, hasDiffRanges, codeql, logger) {
-  if (config.overlayDatabaseMode === "overlay" /* Overlay */ && !hasDiffRanges) {
+  if (config.overlayDatabaseMode === "overlay" /* Overlay */ && !hasDiffRanges && !config.overlayModeSetExplicitly) {
     logger.info(
       `Reverting overlay database mode to ${"none" /* None */} because the PR diff ranges could not be computed.`
     );
@@ -152052,12 +152152,17 @@ async function initConfig(features, inputs) {
     logger
   );
   if (overlayDatabaseModeResult.isSuccess()) {
-    const { overlayDatabaseMode, useOverlayDatabaseCaching } = overlayDatabaseModeResult.value;
+    const {
+      overlayDatabaseMode,
+      useOverlayDatabaseCaching,
+      overlayModeSetExplicitly
+    } = overlayDatabaseModeResult.value;
     logger.info(
       `Using overlay database mode: ${overlayDatabaseMode} ${useOverlayDatabaseCaching ? "with" : "without"} caching.`
     );
     config.overlayDatabaseMode = overlayDatabaseMode;
     config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
+    config.overlayModeSetExplicitly = overlayModeSetExplicitly;
   } else {
     const overlayDisabledReason = overlayDatabaseModeResult.value;
     logger.info(
@@ -153805,7 +153910,7 @@ async function getCodeQLForCmd(cmd, checkVersion) {
       return cmd;
     },
     async getVersion() {
-      let result = getCachedCodeQlVersion();
+      let result = getCachedCodeQlVersion(cmd);
       if (result === void 0) {
         const output = await runCli(cmd, ["version", "--format=json"], {
           noStreamStdout: true
@@ -153817,12 +153922,12 @@ async function getCodeQLForCmd(cmd, checkVersion) {
             `Invalid JSON output from \`version --format=json\`: ${output}`
           );
         }
-        cacheCodeQlVersion(result);
+        cacheCodeQlVersion(cmd, result);
       }
       return result;
     },
     async printVersion() {
-      await runCli(cmd, ["version", "--format=json"]);
+      core11.info(JSON.stringify(await this.getVersion(), null, 2));
     },
     async supportsFeature(feature) {
       return isSupportedToolsFeature(await this.getVersion(), feature);
@@ -157430,22 +157535,20 @@ function dumpSarifFile(sarifPayload, outputDir, logger, uploadTarget) {
   logger.info(`Writing processed SARIF file to ${outputFile}`);
   fs21.writeFileSync(outputFile, sarifPayload);
 }
-var STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1e3;
-var STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1e3;
+var STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS = 5 * 1e3;
+var STATUS_CHECK_BACKOFF_MULTIPLIER = 2;
+var STATUS_CHECK_MAX_TRIES = 5;
 async function waitForProcessing(repositoryNwo, sarifID, logger, options = {
   isUnsuccessfulExecution: false
 }) {
   logger.startGroup("Waiting for processing to finish");
   try {
     const client = getApiClient();
-    const statusCheckingStarted = Date.now();
-    while (true) {
-      if (Date.now() > statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS) {
-        logger.warning(
-          "Timed out waiting for analysis to finish processing. Continuing."
-        );
-        break;
-      }
+    let statusCheckBackoff = STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS;
+    if (process.env["NODE_ENV"] !== "test") {
+      await delay(statusCheckBackoff, { allowProcessExit: false });
+    }
+    for (let statusCheckCount = 1; statusCheckCount <= STATUS_CHECK_MAX_TRIES; statusCheckCount++) {
       let response = void 0;
       try {
         response = await client.request(
@@ -157483,9 +157586,15 @@ ${response.data.errors}`;
       } else {
         assertNever(status);
       }
-      await delay(STATUS_CHECK_FREQUENCY_MILLISECONDS, {
-        allowProcessExit: false
-      });
+      if (statusCheckCount === STATUS_CHECK_MAX_TRIES) {
+        logger.warning(
+          "Timed out waiting for analysis to finish processing. Continuing."
+        );
+        break;
+      } else {
+        statusCheckBackoff *= STATUS_CHECK_BACKOFF_MULTIPLIER;
+        await delay(statusCheckBackoff, { allowProcessExit: false });
+      }
     }
   } finally {
     logger.endGroup();
@@ -159289,6 +159398,9 @@ exec ${goBinaryPath} "$@"`
     if (await features.getValue("disable_kotlin_analysis_enabled" /* DisableKotlinAnalysisEnabled */)) {
       core21.exportVariable("CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN", "true");
     }
+    if (await features.getValue("force_jgit" /* ForceJGit */)) {
+      core21.exportVariable("CODEQL_GIT_BACKEND", "jgit");
+    }
     const kotlinLimitVar = "CODEQL_EXTRACTOR_KOTLIN_OVERRIDE_MAXIMUM_VERSION_LIMIT";
     if (await codeQlVersionAtLeast(codeql, "2.20.3") && !await codeQlVersionAtLeast(codeql, "2.20.4")) {
       core21.exportVariable(kotlinLimitVar, "2.1.20");
diff --git package.json package.json
index ffc4ed7ff8..ec33e335b0 100644
--- package.json
+++ package.json
@@ -1,6 +1,6 @@
 {
   "name": "codeql",
-  "version": "4.36.0",
+  "version": "4.36.2",
   "private": true,
   "description": "CodeQL action",
   "scripts": {
@@ -40,18 +40,18 @@
     "jsonschema": "1.5.0",
     "long": "^5.3.2",
     "node-forge": "^1.4.0",
-    "semver": "^7.7.4",
+    "semver": "^7.8.1",
     "uuid": "^14.0.0"
   },
   "devDependencies": {
     "@ava/typescript": "6.0.0",
-    "@eslint/compat": "^2.0.5",
+    "@eslint/compat": "^2.1.0",
     "@microsoft/eslint-formatter-sarif": "^3.1.0",
     "@octokit/types": "^16.0.0",
     "@types/archiver": "^7.0.0",
     "@types/follow-redirects": "^1.14.4",
     "@types/js-yaml": "^4.0.9",
-    "@types/node": "^20.19.39",
+    "@types/node": "^20.19.41",
     "@types/node-forge": "^1.3.14",
     "@types/sarif": "^2.1.7",
     "@types/semver": "^7.7.1",
@@ -66,10 +66,10 @@
     "eslint-plugin-no-async-foreach": "^0.1.1",
     "glob": "^11.1.0",
     "globals": "^17.6.0",
-    "nock": "^14.0.12",
+    "nock": "^14.0.15",
     "sinon": "^22.0.0",
     "typescript": "^6.0.3",
-    "typescript-eslint": "^8.59.2"
+    "typescript-eslint": "^8.60.0"
   },
   "overrides": {
     "@actions/tool-cache": {
diff --git pr-checks/checks/analysis-kinds.yml pr-checks/checks/analysis-kinds.yml
index 7b10f8d792..5b2aaf4aad 100644
--- pr-checks/checks/analysis-kinds.yml
+++ pr-checks/checks/analysis-kinds.yml
@@ -46,7 +46,7 @@ steps:
       post-processed-sarif-path: "${{ runner.temp }}/post-processed"
 
   - name: Upload SARIF files
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: |
         analysis-kinds-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
@@ -54,7 +54,7 @@ steps:
       retention-days: 7
 
   - name: Upload post-processed SARIF
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: |
         post-processed-${{ matrix.os }}-${{ matrix.version }}-${{ matrix.analysis-kinds }}
@@ -64,7 +64,7 @@ steps:
 
   - name: Check quality query does not appear in security SARIF
     if: contains(matrix.analysis-kinds, 'code-scanning')
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
       EXPECT_PRESENT: "false"
@@ -72,7 +72,7 @@ steps:
       script: ${{ env.CHECK_SCRIPT }}
   - name: Check quality query appears in quality SARIF
     if: contains(matrix.analysis-kinds, 'code-quality')
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: "${{ runner.temp }}/results/javascript.quality.sarif"
       EXPECT_PRESENT: "true"
diff --git pr-checks/checks/bundle-from-toolcache.yml pr-checks/checks/bundle-from-toolcache.yml
index 2719ccfb00..0e51e2e12b 100644
--- pr-checks/checks/bundle-from-toolcache.yml
+++ pr-checks/checks/bundle-from-toolcache.yml
@@ -7,7 +7,7 @@ steps:
     run: npm install @actions/tool-cache@3
   - name: Check toolcache contains CodeQL
     continue-on-error: true
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     with:
       script: |
         const toolcache = require('@actions/tool-cache');
@@ -20,7 +20,7 @@ steps:
     with:
       tools: ${{ steps.prepare-test.outputs.tools-url }}
   - name: Check CodeQL is installed within the toolcache
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     with:
       script: |
         const toolcache = require('@actions/tool-cache');
diff --git pr-checks/checks/bundle-toolcache.yml pr-checks/checks/bundle-toolcache.yml
index f5315d285a..83d1d7d0b5 100644
--- pr-checks/checks/bundle-toolcache.yml
+++ pr-checks/checks/bundle-toolcache.yml
@@ -8,7 +8,7 @@ operatingSystems:
   - windows
 steps:
   - name: Remove CodeQL from toolcache
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     with:
       script: |
         const fs = require('fs');
@@ -18,7 +18,7 @@ steps:
   - name: Install @actions/tool-cache
     run: npm install @actions/tool-cache@3
   - name: Check toolcache does not contain CodeQL
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     with:
       script: |
         const toolcache = require('@actions/tool-cache');
@@ -37,7 +37,7 @@ steps:
       output: ${{ runner.temp }}/results
       upload-database: false
   - name: Check CodeQL is installed within the toolcache
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     with:
       script: |
         const toolcache = require('@actions/tool-cache');
diff --git pr-checks/checks/bundle-zstd.yml pr-checks/checks/bundle-zstd.yml
index 810f0b0c12..a961af3c36 100644
--- pr-checks/checks/bundle-zstd.yml
+++ pr-checks/checks/bundle-zstd.yml
@@ -8,7 +8,7 @@ operatingSystems:
   - windows
 steps:
   - name: Remove CodeQL from toolcache
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     with:
       script: |
         const fs = require('fs');
@@ -27,13 +27,13 @@ steps:
       output: ${{ runner.temp }}/results
       upload-database: false
   - name: Upload SARIF
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: ${{ matrix.os }}-zstd-bundle.sarif
       path: ${{ runner.temp }}/results/javascript.sarif
       retention-days: 7
   - name: Check diagnostic with expected tools URL appears in SARIF
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: ${{ runner.temp }}/results/javascript.sarif
     with:
diff --git pr-checks/checks/config-export.yml pr-checks/checks/config-export.yml
index 17dd758453..93c6407355 100644
--- pr-checks/checks/config-export.yml
+++ pr-checks/checks/config-export.yml
@@ -14,13 +14,13 @@ steps:
       output: "${{ runner.temp }}/results"
       upload-database: false
   - name: Upload SARIF
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: config-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
       path: "${{ runner.temp }}/results/javascript.sarif"
       retention-days: 7
   - name: Check config properties appear in SARIF
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
     with:
diff --git pr-checks/checks/diagnostics-export.yml pr-checks/checks/diagnostics-export.yml
index 811335a7c7..61b9ae5efc 100644
--- pr-checks/checks/diagnostics-export.yml
+++ pr-checks/checks/diagnostics-export.yml
@@ -27,13 +27,13 @@ steps:
       output: "${{ runner.temp }}/results"
       upload-database: false
   - name: Upload SARIF
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: diagnostics-export-${{ matrix.os }}-${{ matrix.version }}.sarif.json
       path: "${{ runner.temp }}/results/javascript.sarif"
       retention-days: 7
   - name: Check diagnostics appear in SARIF
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: "${{ runner.temp }}/results/javascript.sarif"
     with:
diff --git pr-checks/checks/export-file-baseline-information.yml pr-checks/checks/export-file-baseline-information.yml
index 8f882ef598..c5d5d12dda 100644
--- pr-checks/checks/export-file-baseline-information.yml
+++ pr-checks/checks/export-file-baseline-information.yml
@@ -23,7 +23,7 @@ steps:
     with:
       output: "${{ runner.temp }}/results"
   - name: Upload SARIF
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: with-baseline-information-${{ matrix.os }}-${{ matrix.version }}.sarif.json
       path: "${{ runner.temp }}/results/javascript.sarif"
diff --git pr-checks/checks/go-indirect-tracing-workaround-diagnostic.yml pr-checks/checks/go-indirect-tracing-workaround-diagnostic.yml
index bd48f1a12c..69f9b47621 100644
--- pr-checks/checks/go-indirect-tracing-workaround-diagnostic.yml
+++ pr-checks/checks/go-indirect-tracing-workaround-diagnostic.yml
@@ -12,7 +12,7 @@ steps:
       languages: go
       tools: ${{ steps.prepare-test.outputs.tools-url }}
   # Deliberately change Go after the `init` step
-  - uses: actions/setup-go@v6
+  - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0
     with:
       go-version: "1.20"
   - name: Build code
@@ -22,7 +22,7 @@ steps:
       output: "${{ runner.temp }}/results"
       upload-database: false
   - name: Check diagnostic appears in SARIF
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: "${{ runner.temp }}/results/go.sarif"
     with:
diff --git pr-checks/checks/go-indirect-tracing-workaround-no-file-program.yml pr-checks/checks/go-indirect-tracing-workaround-no-file-program.yml
index 8e3f4234b5..5068df622b 100644
--- pr-checks/checks/go-indirect-tracing-workaround-no-file-program.yml
+++ pr-checks/checks/go-indirect-tracing-workaround-no-file-program.yml
@@ -23,7 +23,7 @@ steps:
       output: "${{ runner.temp }}/results"
       upload-database: false
   - name: Check diagnostic appears in SARIF
-    uses: actions/github-script@v8
+    uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
     env:
       SARIF_PATH: "${{ runner.temp }}/results/go.sarif"
     with:
diff --git pr-checks/checks/job-run-uuid-sarif.yml pr-checks/checks/job-run-uuid-sarif.yml
index b37821d5a1..dc1dd02d43 100644
--- pr-checks/checks/job-run-uuid-sarif.yml
+++ pr-checks/checks/job-run-uuid-sarif.yml
@@ -12,7 +12,7 @@ steps:
     with:
       output: "${{ runner.temp }}/results"
   - name: Upload SARIF
-    uses: actions/upload-artifact@v7
+    uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
     with:
       name: ${{ matrix.os }}-${{ matrix.version }}.sarif.json
       path: "${{ runner.temp }}/results/javascript.sarif"
diff --git pr-checks/checks/multi-language-autodetect.yml pr-checks/checks/multi-language-autodetect.yml
index c52dcf9401..fcafe5fb35 100644
--- pr-checks/checks/multi-language-autodetect.yml
+++ pr-checks/checks/multi-language-autodetect.yml
@@ -13,7 +13,7 @@ steps:
     # We need Python 3.13 for older CLI versions because they are not compatible with Python 3.14 or newer.
     # See https://github.com/github/codeql-action/pull/3212
     if: matrix.version != 'nightly-latest' && matrix.version != 'linked'
-    uses: actions/setup-python@v6
+    uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6.2.0
     with:
       python-version: "3.13"
 
diff --git pr-checks/checks/rubocop-multi-language.yml pr-checks/checks/rubocop-multi-language.yml
index fdf6c913bb..35135a545b 100644
--- pr-checks/checks/rubocop-multi-language.yml
+++ pr-checks/checks/rubocop-multi-language.yml
@@ -5,7 +5,7 @@ versions:
   - default
 steps:
   - name: Set up Ruby
-    uses: ruby/setup-ruby@c4e5b1316158f92e3d49443a9d58b31d25ac0f8f # v1.306.0
+    uses: ruby/setup-ruby@afeafc3d1ab54a631816aba4c914a0081c12ff2f # v1.310.0
     with:
       ruby-version: 2.6
   - name: Install Code Scanning integration
diff --git pr-checks/checks/submit-sarif-failure.yml pr-checks/checks/submit-sarif-failure.yml
index e776e23c24..2bba971d72 100644
--- pr-checks/checks/submit-sarif-failure.yml
+++ pr-checks/checks/submit-sarif-failure.yml
@@ -21,7 +21,7 @@ permissions:
   security-events: write # needed to upload the SARIF file
 
 steps:
-  - uses: actions/checkout@v6
+  - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
   - uses: ./init
     with:
       languages: javascript
diff --git pr-checks/checks/with-checkout-path.yml pr-checks/checks/with-checkout-path.yml
index c53e3b4153..e91066e18e 100644
--- pr-checks/checks/with-checkout-path.yml
+++ pr-checks/checks/with-checkout-path.yml
@@ -14,7 +14,7 @@ steps:
       rm -rf ./* .github .git
   # Check out the actions repo again, but at a different location.
   # choose an arbitrary SHA so that we can later test that the commit_oid is not from main
-  - uses: actions/checkout@v6
+  - uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
     with:
       ref: 474bbf07f9247ffe1856c6a0f94aeeb10e7afee6
       path: x/y/z/some-path
diff --git pr-checks/package.json pr-checks/package.json
index 2741560f68..02b841e6d5 100644
--- pr-checks/package.json
+++ pr-checks/package.json
@@ -7,10 +7,10 @@
     "@octokit/core": "^7.0.6",
     "@octokit/plugin-paginate-rest": ">=9.2.2",
     "@octokit/plugin-rest-endpoint-methods": "^17.0.0",
-    "yaml": "^2.8.4"
+    "yaml": "^2.9.0"
   },
   "devDependencies": {
-    "@types/node": "^20.19.39",
-    "tsx": "^4.21.0"
+    "@types/node": "^20.19.41",
+    "tsx": "^4.22.3"
   }
 }
diff --git pr-checks/sync-back.test.ts pr-checks/sync-back.test.ts
index 8b46217492..52d4c98f3f 100755
--- pr-checks/sync-back.test.ts
+++ pr-checks/sync-back.test.ts
@@ -188,6 +188,41 @@ const steps = [
     const result = updateSyncTs(syncTsPath, actionVersions);
     assert.equal(result, false);
   });
+
+  await it("updates SHA-pinned pinnedUses references", () => {
+    /** Test updating `pinnedUses(...)` references with new SHA and version */
+    const syncTsContent = `
+const steps = [
+  {
+    uses: pinnedUses(
+      "actions/setup-node",
+      "0000000000000000000000000000000000000000",
+      "v6.0.0",
+    ),
+  },
+];
+`;
+
+    fs.writeFileSync(syncTsPath, syncTsContent);
+
+    const actionVersions = {
+      "actions/setup-node": "48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0",
+    };
+
+    const result = updateSyncTs(syncTsPath, actionVersions);
+    assert.equal(result, true);
+
+    const updatedContent = fs.readFileSync(syncTsPath, "utf8");
+
+    assert.ok(
+      updatedContent.includes('"48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e"'),
+    );
+    assert.ok(updatedContent.includes('"v6.4.0"'));
+    assert.ok(
+      !updatedContent.includes("0000000000000000000000000000000000000000"),
+    );
+    assert.ok(!updatedContent.includes('"v6.0.0"'));
+  });
 });
 
 describe("updateTemplateFiles", async () => {
diff --git pr-checks/sync-back.ts pr-checks/sync-back.ts
index 5d7275e812..bb442b2fe1 100755
--- pr-checks/sync-back.ts
+++ pr-checks/sync-back.ts
@@ -68,6 +68,10 @@ export function scanGeneratedWorkflows(
 /**
  * Update hardcoded action versions in pr-checks/sync.ts
  *
+ * Handles both inline `uses: "owner/action@ref"` strings and SHA-pinned
+ * references expressed via the `pinnedUses("owner/action", "<sha>", "version")`
+ * helper.
+ *
  * @param syncTsPath - Path to sync.ts file
  * @param actionVersions - Map of action names to versions (may include comments)
  * @returns True if the file was modified, false otherwise
@@ -87,18 +91,36 @@ export function updateSyncTs(
   for (const [actionName, versionWithComment] of Object.entries(
     actionVersions,
   )) {
-    // Extract just the version part (before any comment) for sync.ts
-    const version = versionWithComment.includes("#")
+    // Split the scanned value into the ref (e.g. a commit SHA) and the optional
+    // trailing version comment (e.g. `v6.0.3`).
+    const ref = versionWithComment.includes("#")
       ? versionWithComment.split("#")[0].trim()
       : versionWithComment.trim();
+    const versionComment = versionWithComment.includes("#")
+      ? versionWithComment.split("#")[1].trim()
+      : "";
+
+    const escaped = actionName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
 
     // Look for patterns like uses: "actions/setup-node@v4"
     // Note that this will break if we store an Action uses reference in a
     // variable - that's a risk we're happy to take since in that case the
     // PR checks will just fail.
-    const escaped = actionName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
-    const pattern = new RegExp(`(uses:\\s*")${escaped}@(?:[^"]+)(")`, "g");
-    content = content.replace(pattern, `$1${actionName}@${version}$2`);
+    const usesPattern = new RegExp(`(uses:\\s*")${escaped}@(?:[^"]+)(")`, "g");
+    content = content.replace(usesPattern, `$1${actionName}@${ref}$2`);
+
+    // Look for SHA-pinned references expressed via the `pinnedUses` helper, e.g.
+    // `pinnedUses("actions/checkout", "<sha>", "v6.0.3")`, updating both the
+    // pinned ref and the version comment.
+    const pinnedPattern = new RegExp(
+      `(pinnedUses\\(\\s*")${escaped}("\\s*,\\s*")[^"]*("\\s*,\\s*")([^"]*)(")`,
+      "g",
+    );
+    content = content.replace(
+      pinnedPattern,
+      (_match, p1, p2, p3, oldVersion, p5) =>
+        `${p1}${actionName}${p2}${ref}${p3}${versionComment || oldVersion}${p5}`,
+    );
   }
 
   if (content !== originalContent) {
diff --git pr-checks/sync.ts pr-checks/sync.ts
index 27b1d92645..4d7ae200a4 100755
--- pr-checks/sync.ts
+++ pr-checks/sync.ts
@@ -7,6 +7,16 @@ import * as yaml from "yaml";
 
 import { BuiltInLanguage } from "../src/languages";
 
+/**
+ * Returns a `uses` value for `action` pinned to a commit SHA, with the
+ * human-readable version recorded in a trailing comment.
+ */
+function pinnedUses(action: string, sha: string, version: string): yaml.Scalar {
+  const node = new yaml.Scalar(`${action}@${sha}`);
+  node.comment = ` ${version}`;
+  return node;
+}
+
 /** Known workflow input names. */
 enum KnownInputName {
   GoVersion = "go-version",
@@ -192,7 +202,11 @@ const languageSetups: LanguageSetups = {
     steps: [
       {
         name: "Install Node.js",
-        uses: "actions/setup-node@v6",
+        uses: pinnedUses(
+          "actions/setup-node",
+          "48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e",
+          "v6.4.0",
+        ),
         with: {
           "node-version": defaultLanguageVersions.javascript,
           cache: "npm",
@@ -210,7 +224,11 @@ const languageSetups: LanguageSetups = {
     steps: [
       {
         name: "Install Go",
-        uses: "actions/setup-go@v6",
+        uses: pinnedUses(
+          "actions/setup-go",
+          "4a3601121dd01d1626a1e23e37211e3254c1c06c",
+          "v6.4.0",
+        ),
         with: {
           "go-version": `\${{ inputs.go-version || '${defaultLanguageVersions.go}' }}`,
           // to avoid potentially misleading autobuilder results where we expect it to download
@@ -226,7 +244,11 @@ const languageSetups: LanguageSetups = {
     steps: [
       {
         name: "Install Java",
-        uses: "actions/setup-java@v5",
+        uses: pinnedUses(
+          "actions/setup-java",
+          "be666c2fcd27ec809703dec50e508c2fdc7f6654",
+          "v5.2.0",
+        ),
         with: {
           "java-version": `\${{ inputs.java-version || '${defaultLanguageVersions.java}' }}`,
           distribution: "temurin",
@@ -240,7 +262,11 @@ const languageSetups: LanguageSetups = {
     steps: [
       {
         name: "Install Python",
-        uses: "actions/setup-python@v6",
+        uses: pinnedUses(
+          "actions/setup-python",
+          "a309ff8b426b58ec0e2a45f0f869d46889d02405",
+          "v6.2.0",
+        ),
         with: {
           "python-version": `\${{ inputs.python-version || '${defaultLanguageVersions.python}' }}`,
         },
@@ -253,7 +279,11 @@ const languageSetups: LanguageSetups = {
     steps: [
       {
         name: "Install .NET",
-        uses: "actions/setup-dotnet@v5",
+        uses: pinnedUses(
+          "actions/setup-dotnet",
+          "9a946fdbd5fb07b82b2f5a4466058b876ab72bb2",
+          "v5.3.0",
+        ),
         with: {
           "dotnet-version": `\${{ inputs.dotnet-version || '${defaultLanguageVersions.csharp}' }}`,
         },
@@ -456,7 +486,11 @@ function generateJob(
   const steps: Step[] = [
     {
       name: "Check out repository",
-      uses: "actions/checkout@v6",
+      uses: pinnedUses(
+        "actions/checkout",
+        "df4cb1c069e1874edd31b4311f1884172cec0e10",
+        "v6.0.3",
+      ),
     },
     ...setupInfo.steps,
     {
diff --git src/api-compatibility.json src/api-compatibility.json
index 2cded5e4cf..435f8f1d6b 100644
--- src/api-compatibility.json
+++ src/api-compatibility.json
@@ -1 +1 @@
-{"maximumVersion": "3.21", "minimumVersion": "3.16"}
+{"maximumVersion": "3.22", "minimumVersion": "3.16"}
diff --git src/codeql.ts src/codeql.ts
index 19f933c39a..afae491a4a 100644
--- src/codeql.ts
+++ src/codeql.ts
@@ -523,7 +523,7 @@ async function getCodeQLForCmd(
       return cmd;
     },
     async getVersion() {
-      let result = util.getCachedCodeQlVersion();
+      let result = util.getCachedCodeQlVersion(cmd);
       if (result === undefined) {
         const output = await runCli(cmd, ["version", "--format=json"], {
           noStreamStdout: true,
@@ -535,12 +535,13 @@ async function getCodeQLForCmd(
             `Invalid JSON output from \`version --format=json\`: ${output}`,
           );
         }
-        util.cacheCodeQlVersion(result);
+        util.cacheCodeQlVersion(cmd, result);
       }
       return result;
     },
     async printVersion() {
-      await runCli(cmd, ["version", "--format=json"]);
+      // Reuse the cached version information rather than invoking the CLI again.
+      core.info(JSON.stringify(await this.getVersion(), null, 2));
     },
     async supportsFeature(feature: ToolsFeature) {
       return isSupportedToolsFeature(await this.getVersion(), feature);
diff --git src/config-utils.test.ts src/config-utils.test.ts
index 10dee55399..25f9293c40 100644
--- src/config-utils.test.ts
+++ src/config-utils.test.ts
@@ -1044,6 +1044,7 @@ const checkOverlayEnablementMacro = makeMacro({
       | {
           overlayDatabaseMode: OverlayDatabaseMode;
           useOverlayDatabaseCaching: boolean;
+          overlayModeSetExplicitly?: boolean;
         }
       | {
           disabledReason: OverlayDisabledReason;
@@ -1124,7 +1125,13 @@ const checkOverlayEnablementMacro = makeMacro({
         if ("disabledReason" in expected) {
           t.deepEqual(result, new Failure(expected.disabledReason));
         } else {
-          t.deepEqual(result, new Success(expected));
+          t.deepEqual(
+            result,
+            new Success({
+              overlayModeSetExplicitly: false,
+              ...expected,
+            }),
+          );
         }
       } finally {
         // Restore the original environment
@@ -1143,6 +1150,7 @@ checkOverlayEnablementMacro.serial(
   {
     overlayDatabaseMode: OverlayDatabaseMode.Overlay,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: true,
   },
 );
 
@@ -1154,6 +1162,7 @@ checkOverlayEnablementMacro.serial(
   {
     overlayDatabaseMode: OverlayDatabaseMode.OverlayBase,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: true,
   },
 );
 
@@ -1812,6 +1821,7 @@ checkOverlayEnablementMacro.serial(
   {
     overlayDatabaseMode: OverlayDatabaseMode.Overlay,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: true,
   },
 );
 
@@ -1824,6 +1834,7 @@ checkOverlayEnablementMacro.serial(
   {
     overlayDatabaseMode: OverlayDatabaseMode.Overlay,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: true,
   },
 );
 
@@ -1920,6 +1931,7 @@ checkOverlayEnablementMacro.serial(
   {
     overlayDatabaseMode: OverlayDatabaseMode.Overlay,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: true,
   },
 );
 
@@ -1965,6 +1977,7 @@ checkOverlayEnablementMacro.serial(
   {
     overlayDatabaseMode: OverlayDatabaseMode.Overlay,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: true,
   },
 );
 
@@ -2182,33 +2195,64 @@ test("applyIncrementalAnalysisSettings: keeps overlay mode and adds exclusions w
   ]);
 });
 
-test("applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable", async (t) => {
-  const config = createTestConfig({
-    overlayDatabaseMode: OverlayDatabaseMode.Overlay,
-  });
-  config.useOverlayDatabaseCaching = true;
-  const codeql = createStubCodeQL({});
-  const logger = getRunnerLogger(true);
-  const addDiagnosticsStub = sinon
-    .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
-    .resolves();
+test.serial(
+  "applyIncrementalAnalysisSettings: disables overlay analysis when diff ranges are unavailable",
+  async (t) => {
+    const config = createTestConfig({
+      overlayDatabaseMode: OverlayDatabaseMode.Overlay,
+    });
+    config.useOverlayDatabaseCaching = true;
+    const codeql = createStubCodeQL({});
+    const logger = getRunnerLogger(true);
+    const addDiagnosticsStub = sinon
+      .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
+      .resolves();
+
+    await configUtils.applyIncrementalAnalysisSettings(
+      config,
+      false,
+      codeql,
+      logger,
+    );
 
-  await configUtils.applyIncrementalAnalysisSettings(
-    config,
-    false,
-    codeql,
-    logger,
-  );
+    t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
+    t.is(config.useOverlayDatabaseCaching, false);
+    t.deepEqual(config.extraQueryExclusions, []);
+    t.true(addDiagnosticsStub.calledOnce);
+    t.is(
+      addDiagnosticsStub.firstCall.args[2],
+      OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
+    );
+  },
+);
 
-  t.is(config.overlayDatabaseMode, OverlayDatabaseMode.None);
-  t.is(config.useOverlayDatabaseCaching, false);
-  t.deepEqual(config.extraQueryExclusions, []);
-  t.true(addDiagnosticsStub.calledOnce);
-  t.is(
-    addDiagnosticsStub.firstCall.args[2],
-    OverlayDisabledReason.DiffInformedAnalysisNotEnabled,
-  );
-});
+test.serial(
+  "applyIncrementalAnalysisSettings: keeps overlay mode when set explicitly and diff ranges are unavailable",
+  async (t) => {
+    const config = createTestConfig({
+      overlayDatabaseMode: OverlayDatabaseMode.Overlay,
+    });
+    config.useOverlayDatabaseCaching = false;
+    config.overlayModeSetExplicitly = true;
+    const codeql = createStubCodeQL({});
+    const logger = getRunnerLogger(true);
+    const addDiagnosticsStub = sinon
+      .stub(overlayDiagnostics, "addOverlayDisablementDiagnostics")
+      .resolves();
+
+    await configUtils.applyIncrementalAnalysisSettings(
+      config,
+      false,
+      codeql,
+      logger,
+    );
+
+    t.is(config.overlayDatabaseMode, OverlayDatabaseMode.Overlay);
+    t.is(config.useOverlayDatabaseCaching, false);
+    t.deepEqual(config.extraQueryExclusions, []);
+    t.true(addDiagnosticsStub.notCalled);
+  },
+);
 
 test("applyIncrementalAnalysisSettings: adds exclusions for diff-informed-only runs", async (t) => {
   const config = createTestConfig({});
diff --git src/config-utils.ts src/config-utils.ts
index 87329fce2e..f4bd761a23 100644
--- src/config-utils.ts
+++ src/config-utils.ts
@@ -243,6 +243,11 @@ export interface Config {
    */
   useOverlayDatabaseCaching: boolean;
 
+  /**
+   * Whether the overlay database mode was set explicitly.
+   */
+  overlayModeSetExplicitly: boolean;
+
   /**
    * A partial mapping from repository properties that affect us to their values.
    */
@@ -573,6 +578,7 @@ export async function initActionState(
     extraQueryExclusions: [],
     overlayDatabaseMode: OverlayDatabaseMode.None,
     useOverlayDatabaseCaching: false,
+    overlayModeSetExplicitly: false,
     repositoryProperties,
     enableFileCoverageInformation,
   };
@@ -772,6 +778,7 @@ async function checkRunnerResources(
 interface EnabledOverlayConfig {
   overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>;
   useOverlayDatabaseCaching: boolean;
+  overlayModeSetExplicitly: boolean;
 }
 
 /**
@@ -826,6 +833,7 @@ export async function checkOverlayEnablement(
     return validateOverlayDatabaseMode(
       modeEnv,
       false,
+      true,
       codeql,
       languages,
       sourceRoot,
@@ -917,6 +925,7 @@ export async function checkOverlayEnablement(
   return validateOverlayDatabaseMode(
     overlayDatabaseMode,
     true,
+    false,
     codeql,
     languages,
     sourceRoot,
@@ -935,6 +944,7 @@ export async function checkOverlayEnablement(
 async function validateOverlayDatabaseMode(
   overlayDatabaseMode: Exclude<OverlayDatabaseMode, OverlayDatabaseMode.None>,
   useOverlayDatabaseCaching: boolean,
+  overlayModeSetExplicitly: boolean,
   codeql: CodeQL,
   languages: Language[],
   sourceRoot: string,
@@ -1006,6 +1016,7 @@ async function validateOverlayDatabaseMode(
   return new Success({
     overlayDatabaseMode,
     useOverlayDatabaseCaching,
+    overlayModeSetExplicitly,
   });
 }
 
@@ -1080,14 +1091,14 @@ function hasQueryCustomisation(userConfig: UserConfig): boolean {
 /**
  * Finalize the incremental-analysis configuration for this run.
  *
- * Overlay analysis has only been validated in combination with diff-informed
- * analysis, so if `Overlay` mode was selected for a pull request but the diff
- * ranges could not be computed, fall back to a full non-overlay analysis.
+ * Overlay analysis has only been validated in combination with diff-informed analysis, so if
+ * `Overlay` mode was selected for a pull request but the diff ranges could not be computed, fall
+ * back to a full non-overlay analysis. If the overlay mode was set explicitly, this fallback does
+ * not apply.
  *
- * Query exclusions for incremental-only queries are then applied whenever the
- * diff ranges are available — which, after the fallback above, is exactly the
- * set of runs where any kind of incremental analysis (overlay or
- * diff-informed) is in effect.
+ * Query exclusions for incremental-only queries are then applied whenever the diff ranges are
+ * available — which, after the fallback above, is exactly the set of runs where any kind of
+ * incremental analysis (overlay or diff-informed) is in effect.
  */
 export async function applyIncrementalAnalysisSettings(
   config: Config,
@@ -1097,7 +1108,8 @@ export async function applyIncrementalAnalysisSettings(
 ): Promise<void> {
   if (
     config.overlayDatabaseMode === OverlayDatabaseMode.Overlay &&
-    !hasDiffRanges
+    !hasDiffRanges &&
+    !config.overlayModeSetExplicitly
   ) {
     logger.info(
       `Reverting overlay database mode to ${OverlayDatabaseMode.None} ` +
@@ -1251,14 +1263,18 @@ export async function initConfig(
     logger,
   );
   if (overlayDatabaseModeResult.isSuccess()) {
-    const { overlayDatabaseMode, useOverlayDatabaseCaching } =
-      overlayDatabaseModeResult.value;
+    const {
+      overlayDatabaseMode,
+      useOverlayDatabaseCaching,
+      overlayModeSetExplicitly,
+    } = overlayDatabaseModeResult.value;
     logger.info(
       `Using overlay database mode: ${overlayDatabaseMode} ` +
         `${useOverlayDatabaseCaching ? "with" : "without"} caching.`,
     );
     config.overlayDatabaseMode = overlayDatabaseMode;
     config.useOverlayDatabaseCaching = useOverlayDatabaseCaching;
+    config.overlayModeSetExplicitly = overlayModeSetExplicitly;
   } else {
     const overlayDisabledReason = overlayDatabaseModeResult.value;
     logger.info(
diff --git src/defaults.json src/defaults.json
index a57ede64b9..7c82ff2a6e 100644
--- src/defaults.json
+++ src/defaults.json
@@ -1,6 +1,6 @@
 {
-  "bundleVersion": "codeql-bundle-v2.25.5",
-  "cliVersion": "2.25.5",
-  "priorBundleVersion": "codeql-bundle-v2.25.4",
-  "priorCliVersion": "2.25.4"
+  "bundleVersion": "codeql-bundle-v2.25.6",
+  "cliVersion": "2.25.6",
+  "priorBundleVersion": "codeql-bundle-v2.25.5",
+  "priorCliVersion": "2.25.5"
 }
diff --git src/environment.ts src/environment.ts
index ed44ddcff2..c3f54ebd27 100644
--- src/environment.ts
+++ src/environment.ts
@@ -17,6 +17,12 @@ export enum EnvVar {
    */
   CLI_VERBOSITY = "CODEQL_VERBOSITY",
 
+  /**
+   * `PersistedVersionInfo` for the CodeQL CLI, so later Actions steps can reuse it instead of
+   * invoking `codeql version` again.
+   */
+  CODEQL_VERSION_INFO = "CODEQL_ACTION_CLI_VERSION_INFO",
+
   /** Whether the CodeQL Action has invoked the Go autobuilder. */
   DID_AUTOBUILD_GOLANG = "CODEQL_ACTION_DID_AUTOBUILD_GOLANG",
 
diff --git src/feature-flags.ts src/feature-flags.ts
index 6b40d04dab..05a2611426 100644
--- src/feature-flags.ts
+++ src/feature-flags.ts
@@ -82,6 +82,11 @@ export enum Feature {
   DisableJavaBuildlessEnabled = "disable_java_buildless_enabled",
   DisableKotlinAnalysisEnabled = "disable_kotlin_analysis_enabled",
   ExportDiagnosticsEnabled = "export_diagnostics_enabled",
+  /**
+   * Emergency override that forces the CodeQL CLI to use the JGit-based Git backend instead of its
+   * default backend selection.
+   */
+  ForceJGit = "force_jgit",
   ForceNightly = "force_nightly",
   IgnoreGeneratedFiles = "ignore_generated_files",
   JavaNetworkDebugging = "java_network_debugging",
@@ -224,6 +229,11 @@ export const featureConfig = {
     legacyApi: true,
     minimumVersion: undefined,
   },
+  [Feature.ForceJGit]: {
+    defaultValue: false,
+    envVar: "CODEQL_ACTION_FORCE_JGIT",
+    minimumVersion: undefined,
+  },
   [Feature.ForceNightly]: {
     defaultValue: false,
     envVar: "CODEQL_ACTION_FORCE_NIGHTLY",
diff --git src/init-action.ts src/init-action.ts
index 9d2619b1d1..b7593a51cc 100644
--- src/init-action.ts
+++ src/init-action.ts
@@ -614,6 +614,11 @@ async function run(startedAt: Date) {
       core.exportVariable("CODEQL_EXTRACTOR_JAVA_AGENT_DISABLE_KOTLIN", "true");
     }
 
+    // Emergency override to force the CodeQL CLI back to the JGit-based Git backend.
+    if (await features.getValue(Feature.ForceJGit)) {
+      core.exportVariable("CODEQL_GIT_BACKEND", "jgit");
+    }
+
     const kotlinLimitVar =
       "CODEQL_EXTRACTOR_KOTLIN_OVERRIDE_MAXIMUM_VERSION_LIMIT";
     if (
diff --git src/testing-utils.ts src/testing-utils.ts
index 8287d29d61..1702d6835a 100644
--- src/testing-utils.ts
+++ src/testing-utils.ts
@@ -32,6 +32,7 @@ import {
   GitHubVariant,
   GitHubVersion,
   HTTPError,
+  resetCachedCodeQlVersion,
 } from "./util";
 
 export const SAMPLE_DOTCOM_API_DETAILS = {
@@ -101,6 +102,10 @@ export function setupTests(testFn: TestFn<any>) {
     // unless the test explicitly sets one up.
     codeql.setCodeQL({});
 
+    // Reset the in-process CodeQL version cache so that it doesn't leak between
+    // tests, which each represent a separate Actions step in production.
+    resetCachedCodeQlVersion();
+
     // Replace stdout and stderr so we can record output during tests
     t.context.testOutput = "";
     const processStdoutWrite = process.stdout.write.bind(process.stdout);
@@ -585,6 +590,7 @@ export function createTestConfig(overrides: Partial<Config>): Config {
       extraQueryExclusions: [],
       overlayDatabaseMode: OverlayDatabaseMode.None,
       useOverlayDatabaseCaching: false,
+      overlayModeSetExplicitly: false,
       repositoryProperties: {},
       enableFileCoverageInformation: true,
     } satisfies Config,
diff --git src/upload-lib.ts src/upload-lib.ts
index 83331aeed9..83d1eaffb0 100644
--- src/upload-lib.ts
+++ src/upload-lib.ts
@@ -829,8 +829,10 @@ function dumpSarifFile(
   fs.writeFileSync(outputFile, sarifPayload);
 }
 
-const STATUS_CHECK_FREQUENCY_MILLISECONDS = 5 * 1000;
-const STATUS_CHECK_TIMEOUT_MILLISECONDS = 2 * 60 * 1000;
+// Should lead to status checks after 5s, 15s, 35s, 75s, and 155s.
+const STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS = 5 * 1000;
+const STATUS_CHECK_BACKOFF_MULTIPLIER = 2;
+const STATUS_CHECK_MAX_TRIES = 5;
 
 type ProcessingStatus = "pending" | "complete" | "failed";
 
@@ -854,20 +856,17 @@ export async function waitForProcessing(
   try {
     const client = api.getApiClient();
 
-    const statusCheckingStarted = Date.now();
-    while (true) {
-      if (
-        Date.now() >
-        statusCheckingStarted + STATUS_CHECK_TIMEOUT_MILLISECONDS
-      ) {
-        // If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
-        // It's possible the analysis will eventually finish processing, but it's not worth spending more
-        // Actions time waiting.
-        logger.warning(
-          "Timed out waiting for analysis to finish processing. Continuing.",
-        );
-        break;
-      }
+    // Do an initial wait because processing will always take a minimum of 2-3 seconds
+    let statusCheckBackoff = STATUS_CHECK_INITIAL_BACKOFF_MILLISECONDS;
+    if (process.env["NODE_ENV"] !== "test") {
+      await util.delay(statusCheckBackoff, { allowProcessExit: false });
+    }
+
+    for (
+      let statusCheckCount = 1;
+      statusCheckCount <= STATUS_CHECK_MAX_TRIES;
+      statusCheckCount++
+    ) {
       let response: OctokitResponse<any> | undefined = undefined;
       try {
         response = await client.request(
@@ -912,9 +911,18 @@ export async function waitForProcessing(
         util.assertNever(status);
       }
 
-      await util.delay(STATUS_CHECK_FREQUENCY_MILLISECONDS, {
-        allowProcessExit: false,
-      });
+      if (statusCheckCount === STATUS_CHECK_MAX_TRIES) {
+        // If the analysis hasn't finished processing in the allotted time, we continue anyway rather than failing.
+        // It's possible the analysis will eventually finish processing, but it's not worth spending more
+        // Actions time waiting.
+        logger.warning(
+          "Timed out waiting for analysis to finish processing. Continuing.",
+        );
+        break;
+      } else {
+        statusCheckBackoff *= STATUS_CHECK_BACKOFF_MULTIPLIER;
+        await util.delay(statusCheckBackoff, { allowProcessExit: false });
+      }
     }
   } finally {
     logger.endGroup();
diff --git src/util.test.ts src/util.test.ts
index cca457cbe6..3d27e952af 100644
--- src/util.test.ts
+++ src/util.test.ts
@@ -532,3 +532,58 @@ test("Failure.orElse returns the default value for a failure result", (t) => {
   const result = new util.Failure(new Error("test error"));
   t.is(result.orElse("default value"), "default value");
 });
+
+test.serial(
+  "getCachedCodeQlVersion reuses a version persisted by an earlier step",
+  (t) => {
+    process.env[EnvVar.CODEQL_VERSION_INFO] = JSON.stringify({
+      cmd: "/path/to/codeql",
+      version: { version: "2.20.0" },
+    });
+    t.deepEqual(util.getCachedCodeQlVersion("/path/to/codeql"), {
+      version: "2.20.0",
+    });
+  },
+);
+
+test.serial(
+  "getCachedCodeQlVersion ignores a persisted version from a different CLI",
+  (t) => {
+    process.env[EnvVar.CODEQL_VERSION_INFO] = JSON.stringify({
+      cmd: "/path/to/other-codeql",
+      version: { version: "2.20.0" },
+    });
+    t.is(util.getCachedCodeQlVersion("/path/to/codeql"), undefined);
+  },
+);
+
+test.serial(
+  "getCachedCodeQlVersion ignores a malformed persisted value",
+  (t) => {
+    process.env[EnvVar.CODEQL_VERSION_INFO] = "not valid json";
+    t.is(util.getCachedCodeQlVersion("/path/to/codeql"), undefined);
+  },
+);
+
+test.serial(
+  "getCachedCodeQlVersion ignores a persisted value with the wrong structure",
+  (t) => {
+    for (const value of [
+      JSON.stringify({ cmd: "/path/to/codeql" }),
+      JSON.stringify({ cmd: "/path/to/codeql", version: {} }),
+      JSON.stringify({ cmd: "/path/to/codeql", version: { version: 2 } }),
+      JSON.stringify({ version: { version: "2.20.0" } }),
+      JSON.stringify({
+        cmd: "/path/to/codeql",
+        version: { version: "2.20.0", overlayVersion: "1" },
+      }),
+      JSON.stringify({
+        cmd: "/path/to/codeql",
+        version: { version: "2.20.0", features: "nope" },
+      }),
+    ]) {
+      process.env[EnvVar.CODEQL_VERSION_INFO] = value;
+      t.is(util.getCachedCodeQlVersion("/path/to/codeql"), undefined, value);
+    }
+  },
+);
diff --git src/util.ts src/util.ts
index e2331461bd..200d68d2c2 100644
--- src/util.ts
+++ src/util.ts
@@ -619,14 +619,85 @@ export function asHTTPError(arg: any): HTTPError | undefined {
 
 let cachedCodeQlVersion: undefined | VersionInfo = undefined;
 
-export function cacheCodeQlVersion(version: VersionInfo): void {
+/**
+ * Resets the in-process cache of the CodeQL CLI version. Only for use in tests,
+ * which exercise multiple "steps" within a single process.
+ */
+export function resetCachedCodeQlVersion(): void {
+  cachedCodeQlVersion = undefined;
+}
+
+/** The persisted version together with the CLI path it was obtained from. */
+interface PersistedVersionInfo {
+  cmd: string;
+  version: VersionInfo;
+}
+
+function isVersionInfo(x: unknown): x is VersionInfo {
+  const candidate = x as Partial<VersionInfo> | null;
+  return (
+    typeof candidate === "object" &&
+    candidate !== null &&
+    typeof candidate.version === "string" &&
+    (candidate.features === undefined ||
+      (typeof candidate.features === "object" &&
+        candidate.features !== null)) &&
+    (candidate.overlayVersion === undefined ||
+      typeof candidate.overlayVersion === "number")
+  );
+}
+
+function isPersistedVersionInfo(x: unknown): x is PersistedVersionInfo {
+  const candidate = x as Partial<PersistedVersionInfo> | null;
+  return (
+    typeof candidate === "object" &&
+    candidate !== null &&
+    typeof candidate.cmd === "string" &&
+    isVersionInfo(candidate.version)
+  );
+}
+
+export function cacheCodeQlVersion(cmd: string, version: VersionInfo): void {
   if (cachedCodeQlVersion !== undefined) {
     throw new Error("cacheCodeQlVersion() should be called only once");
   }
   cachedCodeQlVersion = version;
+  // Persist the version so that subsequent Actions steps, which run in separate
+  // processes, can reuse it rather than invoking `codeql version` again. We
+  // record the CLI path so that a different step using a different CodeQL bundle
+  // doesn't pick up a stale version.
+  core.exportVariable(
+    EnvVar.CODEQL_VERSION_INFO,
+    JSON.stringify({ cmd, version }),
+  );
 }
 
-export function getCachedCodeQlVersion(): undefined | VersionInfo {
+export function getCachedCodeQlVersion(cmd?: string): undefined | VersionInfo {
+  if (cachedCodeQlVersion !== undefined) {
+    return cachedCodeQlVersion;
+  }
+  // Fall back to the value persisted by an earlier Actions step, if any. This is
+  // best-effort: any malformed or mismatched value is ignored so that the caller
+  // invokes `codeql version` instead.
+  const serialized = process.env[EnvVar.CODEQL_VERSION_INFO];
+  if (!serialized) {
+    return undefined;
+  }
+  let persisted: unknown;
+  try {
+    persisted = JSON.parse(serialized);
+  } catch {
+    return undefined;
+  }
+  if (
+    !isPersistedVersionInfo(persisted) ||
+    (cmd !== undefined && persisted.cmd !== cmd)
+  ) {
+    return undefined;
+  }
+  // Memoize the parsed value so that subsequent calls in this process don't
+  // re-parse the environment variable.
+  cachedCodeQlVersion = persisted.version;
   return cachedCodeQlVersion;
 }
 

Description

Multi-faceted release PR (v4.36.1 → v4.36.2) containing:

  1. Pin all GitHub Actions uses: to commit SHAs across ~60 workflow files and PR check templates, replacing floating tags (@v6, @v8, etc.) with full SHA pins plus version comments.
  2. Cache CodeQL CLI version info across Actions steps via CODEQL_ACTION_CLI_VERSION_INFO env var, avoiding redundant codeql version invocations.
  3. Exponential backoff for SARIF processing status polling — replaces fixed 5s interval / 2min timeout with 5s initial backoff × 2 multiplier × 5 max tries.
  4. ForceJGit feature flag — emergency override to force CodeQL CLI to use JGit-based Git backend (CODEQL_GIT_BACKEND=jgit).
  5. Overlay mode overlayModeSetExplicitly tracking — when overlay mode is set via env var, diff-range unavailability no longer causes fallback to non-overlay analysis.
  6. printVersion optimization — reuses cached version info instead of re-invoking CLI.
  7. pinnedUses() helper in sync.ts — generates YAML scalars with SHA-pinned uses: and version comments; sync-back.ts updated to round-trip these references.
  8. Dependency bumps: semver ^7.8.1, nock ^14.0.15, typescript-eslint ^8.60.0, ruby/setup-ruby v1.310.0, default CodeQL bundle → 2.25.6, API compatibility max → 3.22.
  9. tmp library update (bundled) — path traversal hardening with _assertPath validation.

Possible Issues

  • Backoff total wait changed significantly: Old behavior waited up to 2 minutes (24 polls × 5s). New behavior waits ~155s total across 5 tries but with an initial unconditional 5s delay before the first check, plus a delay after the last failed check is skipped. The if (process.env["NODE_ENV"] !== "test") guard means tests skip the initial delay — this couples production logic to NODE_ENV, which is fragile.
  • resetCachedCodeQlVersion only resets in-process state: The env var CODEQL_ACTION_CLI_VERSION_INFO persists across the test unless the test harness also cleans it. The setupTests helper calls resetCachedCodeQlVersion() but doesn't clear the env var — tests that set this env var and don't clean up could leak.
  • cacheCodeQlVersion still throws on double-call: Cross-step persistence means the in-process cache could be populated from the env var via getCachedCodeQlVersion, then cacheCodeQlVersion called, which wouldn't throw (since getCachedCodeQlVersion sets cachedCodeQlVersion via memoization). However if cacheCodeQlVersion is called twice in the same step, it still throws — this asymmetry is subtle.
  • pinnedUses regex in sync-back.ts: The pinnedPattern captures group 4 (oldVersion) but the replacement uses versionComment || oldVersion — if versionComment is empty string (falsy), it falls back to oldVersion, which is correct. But if a scanned action genuinely has no comment, it preserves the old version string, which could be stale.

Security Hotspots

  • tmp library path traversal fix (bundled in lib/entry-points.js): The _assertPath function now rejects .. in prefix/postfix/template options and fixes the _getRelativePath check from !resolvedPath.startsWith(tmpDir) to relativePath.startsWith("..") || path.isAbsolute(relativePath). The old startsWith check was bypassable with paths like /tmp2/evil when tmpDir is /tmp. This is a positive security improvement.
Changes

Changes

src/util.ts: Added PersistedVersionInfo interface, isVersionInfo/isPersistedVersionInfo type guards, resetCachedCodeQlVersion(). cacheCodeQlVersion now takes cmd param and exports to CODEQL_ACTION_CLI_VERSION_INFO. getCachedCodeQlVersion reads from env var as fallback.

src/upload-lib.ts: Replaced fixed-interval polling with exponential backoff (5s × 2^n, 5 tries max). Added initial delay before first status check (skipped in tests).

src/config-utils.ts: Added overlayModeSetExplicitly to Config and EnabledOverlayConfig. validateOverlayDatabaseMode takes new param. applyIncrementalAnalysisSettings skips overlay fallback when mode was set explicitly.

src/feature-flags.ts: Added ForceJGit feature flag with CODEQL_ACTION_FORCE_JGIT env var.

src/init-action.ts: Sets CODEQL_GIT_BACKEND=jgit when ForceJGit enabled.

src/codeql.ts: printVersion reuses getVersion() cache. Version cache calls pass cmd.

src/environment.ts: Added CODEQL_VERSION_INFO enum value.

pr-checks/sync.ts: Added pinnedUses() helper generating SHA-pinned YAML scalars with version comments. All language setup and checkout steps converted.

pr-checks/sync-back.ts: Extended updateSyncTs to handle pinnedUses(...) patterns alongside inline uses: strings.

.github/workflows/**: ~60 workflow files updated to SHA-pinned action references.

src/defaults.json, lib/defaults.json: Bundle version → 2.25.6.

src/api-compatibility.json: Maximum API version → 3.22.

sequenceDiagram
    participant Init as init-action (Step 1)
    participant Env as Environment Variables
    participant Analyze as analyze-action (Step 2)
    participant API as GitHub API

    Init->>Init: getVersion() → runs `codeql version --format=json`
    Init->>Init: cacheCodeQlVersion(cmd, versionInfo)
    Init->>Env: exportVariable(CODEQL_ACTION_CLI_VERSION_INFO, {cmd, version})
    Init->>Init: Check ForceJGit feature flag
    opt ForceJGit enabled
        Init->>Env: exportVariable(CODEQL_GIT_BACKEND, "jgit")
    end

    Analyze->>Env: getCachedCodeQlVersion(cmd) reads CODEQL_ACTION_CLI_VERSION_INFO
    Analyze->>Analyze: Skips `codeql version` invocation
    Analyze->>Analyze: printVersion() → logs cached JSON

    Analyze->>API: Upload SARIF
    API-->>Analyze: sarifID

    Note over Analyze,API: Exponential backoff polling
    Analyze->>Analyze: delay(5s)
    Analyze->>API: GET /sarif/{sarifID} (try 1)
    API-->>Analyze: pending
    Analyze->>Analyze: delay(10s)
    Analyze->>API: GET /sarif/{sarifID} (try 2)
    API-->>Analyze: complete
Loading

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants