Skip to content

Harden CI: pin the remaining third-party actions to commit SHAs - #5285

Merged
vivekchand merged 1 commit into
mainfrom
harden/pin-third-party-actions
Aug 28, 2026
Merged

vivekchand merged 1 commit into
mainfrom
harden/pin-third-party-actions

Conversation

@vivekchand

Copy link
Copy Markdown
Owner

What

The last PinnedDependencies batch that is not an actions/-org action. Six references across four files, each a 1:1 replacement of a mutable ref with the full commit SHA it resolves to today, plus a version comment.

action was pinned to
browserstack/github-actions/setup-env @master 1ab56d9521ce20f4651bb5d9f3ef39c5ba54805a # master @ 2026-08-28
browserstack/github-actions/setup-local (×2) @master 1ab56d9521ce20f4651bb5d9f3ef39c5ba54805a # master @ 2026-08-28
peter-evans/create-pull-request (×2) @v8 5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1
github/codeql-action/upload-sarif @v3 6f5948dfacef28e207b48d0905cf90c03365536d # v3.37.9

Files: browserstack.yml, i18n-autotranslate.yml, i18n-docs-autotranslate.yml, supply-chain.yml.

The four actions/checkout@v7 / actions/setup-python@v7 refs sitting in the same files are pinned in the same pass, to the SHAs this repository already uses in ci.yml, supply-chain.yml and the release workflows. That keeps one SHA per action across all 34 workflows, so the next bump stays a single sweep.

Why this set, and why now

#5283 called these out as the batch that wanted its own look rather than a sweep, because unlike the earlier batches these are not first-party actions and three of them did not even resolve through a tag.

A branch ref is the weakest thing a workflow can depend on. @master is whatever BrowserStack pushed most recently — the code executed by the next run can change with nothing landing in this repository and nothing to review. @v8 and @v3 are floating major tags, repointable the same way, just more slowly. That is the Scorecard PinnedDependencies class, and it matters more here than for a first-party action because these are third-party repositories with their own release practices.

Two of the six are also unusually well-placed to do damage if the upstream ref moved: peter-evans/create-pull-request runs with the token that opens pull requests against this repository, and the BrowserStack steps receive BROWSERSTACK_USERNAME / BROWSERSTACK_ACCESS_KEY.

Why these SHAs

Each was resolved directly from the upstream repository and then verified by fetching the commit:

  • peter-evans/create-pull-requestrefs/tags/v8 is a lightweight tag pointing at the same commit as v8.1.1, so @v8 resolves there today. Pinned to that commit and labelled with the concrete version.
  • github/codeql-actionrefs/tags/v3 peels to the v3.37.9 commit (Merge pull request #4109 from github/backport-v3.37.9). The v3 line is kept deliberately; chore(deps): bump github/codeql-action from 3 to 4 #5158 proposes the 3→4 bump and that is its call to make, not this PR's.
  • browserstack/github-actions — pinned to the current tip of master rather than to v1.0.4, because master is ahead of the last tag and moving to the tag would be a version rollback of unknown size, not a pin. Preserving today's behaviour is the point; the comment records what the SHA is so the next reader is not left guessing.

Risk

uses: values only. No permissions: block, step, trigger, matrix, runner or run: body is touched, and no action's version changes — only how it is addressed.

Verification:

  • all 34 files under .github/workflows/ re-parsed with yaml.safe_load after the edit;
  • each changed file loaded as a structure and compared against its HEAD version with uses: values masked — the diff is empty, confirming the change is pins and nothing else;
  • each new SHA fetched from its upstream repository, confirming it is a real commit, with the commit subject matching the claimed version;
  • git diff --stat is 12 insertions / 12 deletions across 4 files.

The Action references resolve job in supply-chain.yml re-checks all 23 references against the GitHub API on this PR, which is the authoritative check for this change.

Where this leaves the repo

Every action reference in this repository that is not owned by the actions/ org is now pinned to a commit SHA. TokenPermissions is clean — all 34 workflows declare a top-level permissions: block — and no run: block interpolates ${{ github.event.* }}.

Remaining PinnedDependencies work is first-party only, and splits by version line rather than by family: fourteen workflows still on actions/*@v7, plus actions/setup-python@v6 in overhead-bench.yml / windows-enterprise-tls.yml, actions/cache@v6 in oss-golden-path.yml and actions/upload-artifact@v4 in overhead-bench.yml.

Product record

CI-only: every changed path is under .github/, which is exempt from the product-record gate.

No-PRD: CI/workflow-only change, all paths under .github/ (gate-exempt).


Generated by Claude Code

Every action reference in this repository that is not owned by the
`actions/` org still resolved through a mutable ref. Three of them
pointed at a branch:

  browserstack/github-actions/setup-env@master
  browserstack/github-actions/setup-local@master   (x2)
  peter-evans/create-pull-request@v8               (x2)
  github/codeql-action/upload-sarif@v3

A branch or floating tag is repointable by whoever controls the
upstream repository, so the code these workflows execute can change
with nothing landing here and nothing to review. This replaces each
with the full commit SHA it resolves to today, plus a version comment.

No action's version changes -- only how it is addressed. The four
`actions/checkout` / `actions/setup-python` refs in the same files are
pinned to the SHAs this repo already uses everywhere else, so one SHA
per action holds across all 34 workflows.

Verified: every file under .github/workflows/ re-parsed with
yaml.safe_load; each changed file compared against HEAD as a parsed
structure with `uses:` values masked, and the diff is empty; each new
SHA fetched from its upstream repository to confirm it is a real commit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LMbwMnwYkoSjZ62Zo7J9ec
@8090-software-factory

Copy link
Copy Markdown

✅ Drift Bot (ClawMetry): no drift detected

Drift Bot analyzed the changed files against this project's blueprints and requirements and found no drift.

@vivekchand
vivekchand merged commit 663c295 into main Aug 28, 2026
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants