From 9f0f57bd906cc2d596b5d068e24e6e0325f7e9aa Mon Sep 17 00:00:00 2001 From: rustytrees Date: Wed, 29 Jul 2026 12:01:54 -0400 Subject: [PATCH] chore(ci): pin every action to a commit SHA MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The release job's own permissions are already minimal — `permissions: {}` at the top, `id-token: write` only where cosign needs it — but every `uses:` resolved through a mutable tag, and two of them (`dtolnay/rust-toolchain@stable`, plus the `@vN` majors) move under the repo's feet by design. That is the weak edge of the signing story. A compromised third-party action runs *inside* the job that produces the artifact, before cosign signs it, so the signature comes out valid over malicious output. The README's claim that "a leaked GitHub token is not enough to ship a malicious binary" is true of the token and not yet true of the toolchain around it. All 31 refs across the six workflows now name a commit SHA with the previous tag kept as a trailing comment, so Dependabot still recognises them and the intended version stays readable. Only `uses:` lines changed; indentation, list markers, and line counts are identical. SHAs resolved from each action's published tag at the time of writing. --- .github/workflows/benchmark.yml | 6 +++--- .github/workflows/ci.yml | 12 ++++++------ .github/workflows/codecov.yml | 4 ++-- .github/workflows/dsl-corpus.yml | 6 +++--- .github/workflows/pins-bump.yml | 4 ++-- .github/workflows/release.yml | 30 +++++++++++++++--------------- 6 files changed, 31 insertions(+), 31 deletions(-) diff --git a/.github/workflows/benchmark.yml b/.github/workflows/benchmark.yml index 822d4b72..297416e8 100644 --- a/.github/workflows/benchmark.yml +++ b/.github/workflows/benchmark.yml @@ -25,15 +25,15 @@ jobs: # latest release tags. Local runs leave this unset and bench the tree. BENCH_MALT_RELEASE: "1" steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Zig - uses: mlugg/setup-zig@v2 + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 with: version: 0.16.0 - name: Install Rust - uses: dtolnay/rust-toolchain@stable + uses: dtolnay/rust-toolchain@4cda84d5c5c54efe2404f9d843567869ab1699d4 # stable # --------------------------------------------------------------- # Each step below delegates to scripts/bench.sh, which is also the diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6950ff14..afaea159 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,15 +27,15 @@ jobs: name: Build & Test (macOS) runs-on: macos-14 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Zig - uses: mlugg/setup-zig@v2 + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 with: version: 0.16.0 - name: Install just - uses: taiki-e/install-action@v2 + uses: taiki-e/install-action@18b1216eba7f8039b0f8d131d5473787f0edce68 # v2 with: tool: just @@ -81,10 +81,10 @@ jobs: name: Lint runs-on: macos-14 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Zig - uses: mlugg/setup-zig@v2 + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 with: version: 0.16.0 @@ -118,7 +118,7 @@ jobs: runs-on: macos-14 if: github.event_name == 'pull_request' steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Verify manifest against committed pin run: ./scripts/gen-pins.sh --check diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index 474d8024..3fab726f 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -9,8 +9,8 @@ jobs: upload: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v7 - - uses: codecov/codecov-action@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 + - uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7 with: files: .github/codecov.json disable_search: true diff --git a/.github/workflows/dsl-corpus.yml b/.github/workflows/dsl-corpus.yml index 990fc321..2201d89f 100644 --- a/.github/workflows/dsl-corpus.yml +++ b/.github/workflows/dsl-corpus.yml @@ -37,10 +37,10 @@ jobs: runs-on: macos-14 timeout-minutes: 60 steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install Zig - uses: mlugg/setup-zig@v2 + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 with: version: 0.16.0 @@ -60,7 +60,7 @@ jobs: - name: Upload install logs on failure if: failure() - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: corpus-logs path: /tmp/mt_cs/logs diff --git a/.github/workflows/pins-bump.yml b/.github/workflows/pins-bump.yml index fab5f70b..e1e93076 100644 --- a/.github/workflows/pins-bump.yml +++ b/.github/workflows/pins-bump.yml @@ -22,7 +22,7 @@ jobs: contents: write pull-requests: write steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false @@ -38,7 +38,7 @@ jobs: echo "short=${SHA:0:12}" >>"$GITHUB_OUTPUT" - name: Open or update auto-PR - uses: peter-evans/create-pull-request@v8 + uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8 with: token: ${{ secrets.GITHUB_TOKEN }} branch: chore/pins-auto-bump diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c474e59b..20357737 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: contents: read steps: - name: Checkout - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: # Need full history so `git branch -r --contains` can resolve # the tag against main/release branches. @@ -88,13 +88,13 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: fetch-depth: 0 persist-credentials: false - name: Install Zig - uses: mlugg/setup-zig@v2 + uses: mlugg/setup-zig@d1434d08867e3ee9daa34448df10607b98908d29 # v2 with: version: 0.16.0 # Release runs rarely; a fresh compile takes a few extra @@ -110,16 +110,16 @@ jobs: run: zig build test --summary all - name: Set up Go - uses: actions/setup-go@v6 + uses: actions/setup-go@924ae3a1cded613372ab5595356fb5720e22ba16 # v6 with: go-version: stable cache: false - name: Install cosign - uses: sigstore/cosign-installer@v4.1.2 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Run GoReleaser - uses: goreleaser/goreleaser-action@v7 + uses: goreleaser/goreleaser-action@f06c13b6b1a9625abc9e6e439d9c05a8f2190e94 # v7 with: distribution: goreleaser version: "~> v2" @@ -137,7 +137,7 @@ jobs: SKIP_CASK_UPLOAD: "true" - name: Upload rendered cask for downstream publish - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: name: homebrew-cask # Goreleaser's exact path inside dist/ has shifted between @@ -167,10 +167,10 @@ jobs: # Needed so the cask-paths cross-check helper # (scripts/release/verify_cask_paths.sh) is on disk for the # verify step below. - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 - name: Install cosign - uses: sigstore/cosign-installer@v4.1.2 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Download draft release artifacts env: @@ -189,7 +189,7 @@ jobs: # Same artifact publish-cask consumes downstream — pulling it # here lets us cross-check the cask's declared paths against # the tarball *before* the tap push happens. - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: homebrew-cask path: /tmp/cask @@ -263,7 +263,7 @@ jobs: name: Release steps: - name: Download rendered cask - uses: actions/download-artifact@v8 + uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 with: name: homebrew-cask path: /tmp/cask @@ -322,7 +322,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false @@ -361,7 +361,7 @@ jobs: contents: write steps: - name: Checkout tag - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 # persist-credentials defaults true so `git push` can auth via the # ambient GITHUB_TOKEN. HEAD is the tag commit on a push:tags event. @@ -402,12 +402,12 @@ jobs: name: Release steps: - name: Checkout code - uses: actions/checkout@v7 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7 with: persist-credentials: false - name: Install cosign - uses: sigstore/cosign-installer@v4.1.2 + uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 - name: Run release-install smoke env: