Skip to content

ci: pin GitHub Actions to commit SHAs (supply-chain hardening)#3822

Open
Fabridev444 wants to merge 1 commit into
solana-foundation:maintenance/v1.xfrom
Fabridev444:sec/pin-actions-to-sha
Open

ci: pin GitHub Actions to commit SHAs (supply-chain hardening)#3822
Fabridev444 wants to merge 1 commit into
solana-foundation:maintenance/v1.xfrom
Fabridev444:sec/pin-actions-to-sha

Conversation

@Fabridev444

Copy link
Copy Markdown

What

Pins 26 unpinned action references across 13 workflows to immutable commit SHAs. The original tag is preserved as a trailing # v4 comment so Dependabot keeps auto-bumping the SHA on new releases.

-      - uses: actions/checkout@v4
-      - uses: pnpm/action-setup@v4
-      - uses: actions/setup-node@v4
-      - uses: actions/github-script@v7
+      - uses: actions/checkout@<sha>  # v4
+      - uses: pnpm/action-setup@<sha> # v4
+      - uses: actions/setup-node@<sha># v4
+      - uses: actions/github-script@<sha> # v7

Why this matters specifically for @solana/web3.js

The most critical surface is typescript-publish.yml and publish-legacy-package.yml — they release the @solana/web3.js packages on tag push and call actions/setup-node + actions/github-script with NPM_TOKEN scope. A tag rewrite of any of these (cf. tj-actions/changed-files CVE-2025-30066) compromises the publish pipeline for the JS SDK that every Solana dApp depends on.

The blast radius:

  1. Attacker rewrites actions/github-script@v7 tag → next solana-foundation/solana-web3.js publish runs attacker JS with NPM_TOKEN in env.
  2. Attacker publishes a malicious patch version of @solana/web3.js.
  3. Every dApp that pulls the package on its next npm install ships compromised code to end users with real funds.

Pinning to commit SHAs closes that path: SHAs cannot be rewritten without a force-push that breaks every downstream simultaneously.

This is the GitHub Actions security guide and OpenSSF Scorecard Pinned-Dependencies baseline recommendation.

How

Generated mechanically with gha-shield v1.0.6:

npx Fabridev444/gha-shield .github/workflows --fix

Compatibility

  • ✅ Idempotent — re-running does nothing.
  • ✅ Dependabot reads the # v4 trailing comments and auto-updates SHAs on releases.
  • ✅ Zero behavior change for any workflow trigger.

Other PRs in the same series


gha-shield is MIT (V2+) and self-hosted via npx Fabridev444/gha-shield. Tip jar (Solana / USDC SPL, scannable Solana Pay QR + link): https://fabridev444.github.io/gha-shield/ · wallet 634UtV9dWq8G7ciosqx1pcKkBK4kNkNod9yvoM8ujSdM.

Pins 26 unpinned action refs across 13 workflows to immutable commit
SHAs. Original tag preserved as trailing comment so Dependabot keeps
auto-bumping the SHA on new releases.

Most critical surface: typescript-publish.yml + publish-legacy-package.yml,
which release the @solana/web3.js packages and pull actions/setup-node
+ actions/github-script with NPM_TOKEN scope. A tag rewrite of any of
these (cf. tj-actions/changed-files CVE-2025-30066) would compromise
the publish pipeline for the JS SDK that every Solana dApp depends on.

Generated mechanically with https://github.com/Fabridev444/gha-shield v1.0.6:
  npx Fabridev444/gha-shield .github/workflows --fix
@greptile-apps

greptile-apps Bot commented May 26, 2026

Copy link
Copy Markdown

Greptile Summary

This PR pins 26 GitHub Action references across 13 workflow files from floating version tags (e.g. @v4) to immutable commit SHAs with trailing tag comments. The stated goal is to harden the supply chain, particularly around the NPM_TOKEN-scoped publish pipelines for @solana/web3.js.

  • All SHA pins are structurally correct (consistent across files for the same action+version, correct format), but they were generated by npx Fabridev444/gha-shield — the PR author's own tool — and must be independently verified against GitHub's tag API before merging, especially for the actions used in publish workflows.
  • The PR's claim that "Dependabot auto-updates SHAs on releases" does not hold for this repo: there is no .github/dependabot.yml with a github-actions ecosystem entry, so the pins will become stale and never receive automated updates unless that configuration is added.

Confidence Score: 3/5

Do not merge without independently verifying the pinned SHAs and adding a Dependabot github-actions configuration.

The publish pipeline steps that carry NPM_TOKEN and GITHUB_TOKEN now reference SHAs generated solely by the PR author's own tool. If any SHA points to an unexpected commit, the hardening becomes a disguised injection point. The missing Dependabot config also means these pins will age in place and never receive automated updates, which is the primary operational mechanism the PR relies on for long-term maintenance.

.github/workflows/typescript-publish.yml and .github/workflows/publish-legacy-package.yml carry the highest risk since they run with NPM_TOKEN; all SHA pins in the diff need independent verification via the GitHub API before merging.

Security Review

  • Unverified SHA provenance (typescript-publish.yml, publish-legacy-package.yml, and all 11 other workflow files): All SHA pins were generated by the PR author's own tool (Fabridev444/gha-shield). A single incorrect SHA in the publish path would silently run unintended code with NPM_TOKEN in scope. Each SHA should be cross-checked against gh api repos/<owner>/<action>/git/ref/tags/<version> before merge.
  • No Dependabot github-actions config: Without .github/dependabot.yml, the pinned SHAs will not be auto-updated, causing the pins to drift over time and accumulate unpatched action versions — the opposite of the intended hardening effect.

Important Files Changed

Filename Overview
.github/workflows/typescript-publish.yml SHA-pinned actions/checkout, pnpm/action-setup, actions/setup-node, and actions/github-script (used near NPM_TOKEN / GITHUB_TOKEN publish steps); SHAs are structurally correct but must be independently verified
.github/workflows/publish-legacy-package.yml Only actions/checkout is pinned here; downstream install-dependencies and setup-validator composite actions were already updated in their own files
.github/workflows/actions/install-dependencies/action.yml Pins pnpm/action-setup to v3 SHA and actions/setup-node to v4 SHA; the v3 pin here is correct since the action specifies version 9.1.0 under the v3 API
.github/workflows/preview-gh-pages.yml Pins checkout, download-artifact, peaceiris/actions-gh-pages, peter-evans/find-comment, and actions/github-script
.github/workflows/actions/setup-validator/action.yml Pins actions/cache to a v4 SHA

Comments Outside Diff (1)

  1. .github/workflows/publish-legacy-package.yml, line 1 (link)

    P1 Dependabot will not update these SHA pins without a github-actions configuration

    The PR description claims "Dependabot reads the # v4 trailing comments and auto-updates SHAs on releases," but there is no .github/dependabot.yml in this repository. Dependabot requires an explicit package-ecosystem: "github-actions" entry to discover and update action SHA pins. Without it, all 13 pinned SHAs will drift and never receive automatic updates as new action releases are made — eventually defeating the purpose of pinning.

Reviews (1): Last reviewed commit: "ci: pin GitHub Actions to commit SHAs (s..." | Re-trigger Greptile

- name: Create GitHub Release
if: ${{ github.event.inputs.dry-run != 'true' }}
uses: actions/github-script@v7
uses: actions/github-script@f28e40c7f34bde8b3046d885e986cb6290c5673b # v7

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 security Missing independent SHA verification

All 13 SHA pins in this PR were generated by npx Fabridev444/gha-shield, a tool authored by the same person who submitted this PR. For a supply-chain hardening change that directly protects the NPM_TOKEN-scoped publish pipeline, the SHAs should be independently verified against GitHub's tag API before merging — e.g. by running gh api repos/actions/github-script/git/ref/tags/v7 and confirming the returned object.sha matches f28e40c7f34bde8b3046d885e986cb6290c5673b. The same check applies to every other pinned action. A single wrong SHA here silently executes a different code version (or, in a worst case, an adversarially crafted commit) with GITHUB_TOKEN in scope.

@github-actions github-actions Bot added the stale label Jun 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant