diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e524994..c25fc80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,9 +12,9 @@ jobs: test: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 - - uses: actions/setup-go@v5 + - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 with: go-version-file: go.mod @@ -28,6 +28,23 @@ jobs: exit 1 fi + # A tag is mutable: whoever controls it can repoint it at new code that + # runs with this workflow's token. Pinning to a commit SHA is the only + # form GitHub will not silently resolve to something else, so fail if an + # unpinned `uses:` reappears. + - name: actions are pinned to SHAs + run: | + # Only match `uses:` as a YAML step key (optional "- " then uses:), + # so this check's own grep pattern and comments are not scanned. + all_uses="$(grep -rhoE '^[[:space:]]*-?[[:space:]]*uses:[[:space:]]*[^[:space:]]+' .github/workflows/ \ + | sed -E 's/.*uses:[[:space:]]*//' | sort -u)" + unpinned="$(printf '%s\n' "$all_uses" | grep -vE '@[0-9a-f]{40}$' || true)" + if [ -n "$unpinned" ]; then + echo "these must be pinned to a full 40-character commit SHA:" + printf '%s\n' "$unpinned" + exit 1 + fi + - name: vet run: go vet ./... diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 6eb5f2c..d978820 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -23,7 +23,7 @@ jobs: outputs: tag: ${{ steps.pick.outputs.tag }} steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: fetch-depth: 0 # need all tags to find the latest version @@ -60,14 +60,14 @@ jobs: if: needs.version.outputs.tag != '' runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 with: # Build from the tag itself, not the branch head, so the release is # reproducible even if main moves on while this job runs. ref: ${{ needs.version.outputs.tag }} fetch-depth: 0 # full history so release notes can diff against the previous tag - - uses: actions/setup-go@v5 + - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 with: go-version-file: go.mod