Skip to content

Harden CI: pin supply-chain.yml actions to commit SHAs - #5276

Merged
vivekchand merged 1 commit into
mainfrom
harden/pin-supply-chain-workflow-actions
Aug 28, 2026
Merged

Harden CI: pin supply-chain.yml actions to commit SHAs#5276
vivekchand merged 1 commit into
mainfrom
harden/pin-supply-chain-workflow-actions

Conversation

@vivekchand

Copy link
Copy Markdown
Owner

What

Pins the 13 resolvable action references in .github/workflows/supply-chain.yml to full commit SHAs, with the human-readable version kept in a trailing comment.

Action Pinned to
actions/checkout (6 refs) 3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
actions/setup-python (5 refs) 5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
actions/upload-artifact (2 refs) 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1

Why

A floating tag is resolved at run time, so whoever can move the tag decides what executes in CI. A digest cannot be moved. This is the OpenSSF Scorecard PinnedDependencies probe, and it is particularly apt in this file — supply-chain.yml is the workflow that runs Scorecard, so an unpinned reference here was the workflow failing the check it exists to run. ossf/scorecard-action in this same job was already pinned for exactly that reason.

The trailing # vX.Y.Z comment is the form Dependabot reads, so version bumps keep flowing normally.

Scope

One concern, one workflow file. 13 insertions, 13 deletions, nothing else.

github/codeql-action/upload-sarif@v3 (line 160) is deliberately left on its tag: Dependabot PR #5158 is currently bumping github/codeql-action from 3 to 4, and pinning a v3 digest here would conflict with that bump. It is the only remaining unpinned reference in this file and is best pinned once that bump lands.

ci.yml is not touched — it is covered by the open PR #5275.

Verification

  • Every workflow file parses after the edit, not just the edited one:
    python3 -c "import yaml,glob; [yaml.safe_load(open(f)) for f in glob.glob('.github/workflows/*.yml')]" → 34/34 OK
  • Parsed-YAML comparison against main with uses: values masked is identical, confirming only the action references changed.
  • No permissions: block is added or modified anywhere, so no job's token scope changes.
  • The digests are the same ones already exercised by the ci.yml pinning branch, whose "Action references resolve" check passed green.

Risk

Low. Behaviour-neutral by construction — same actions, same versions, addressed by digest instead of tag. This repo's own "Action references resolve" job validates every reference on this PR.

Path is under .github/, which is exempt from the product-record gate.


Generated by Claude Code

A floating tag resolves at run time, so whoever controls the tag controls
what runs in CI. Pin the 13 resolvable action references in
supply-chain.yml to full commit SHAs, keeping the human-readable version
in a trailing comment so Dependabot can still propose bumps.

Digests are the same ones already validated by the ci.yml pinning branch:
  actions/checkout       v7.0.1
  actions/setup-python   v7.0.0
  actions/upload-artifact v7.0.1

github/codeql-action/upload-sarif is deliberately left on its tag: an open
Dependabot PR is bumping codeql-action from 3 to 4, and pinning it here
would conflict with that bump.

Only `uses:` values change -- the parsed YAML is otherwise identical, and
no permissions block is touched.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LHL2XjNoJMscqDHfYNmVWs
@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.

Copy link
Copy Markdown
Owner Author

E2E Gate (required) is red, and it is not this PR's failure. Recording the evidence rather than pushing anything, since there is nothing in this diff to fix.

What failed: E2E Gate (required)job 98746744703. It did not fail an assertion; it hit its own wait budget:

FAIL: timed out after 1800s. Still pending:
  - Entitlement API tests: 0/1 leg(s) complete

All 11 other required checks it aggregates reported green before the deadline (OSS golden path, Cross-repo handoff, MOAT Keystone, MOAT Verifier, E2E Browser Tests, Syntax & Lint, API Tests ×3, pip install ×4, Wheel install, Store invariants, Drift Bot).

Why it is not this PR's: three independent reasons.

  1. The diff cannot reach it. This PR changes 13 uses: lines in .github/workflows/supply-chain.yml. Entitlement API tests is defined in ci.yml and runs tests/ — no path from one to the other. The parsed YAML of every workflow is unchanged apart from those action references.
  2. The check is red on main too. E2E Gate has failed on the base branch on be87556d (the Harden CI: pin ci.yml actions to commit SHAs #5275 merge commit, today), and earlier on b5b260f7, 5ea3b536 and 41d4accf.
  3. Nothing actually failed on this commit. In CI run 33139437834, 18 of 19 jobs are green. The 19th, Entitlement API tests, picked up a runner at 03:58:22 and was still executing its test suite when the gate's budget expired at 04:09:58. The gate started waiting at 03:39:49; runner scheduling pushed most of this run's jobs to 03:56–03:58, so the suite simply began too late to finish inside the 30-minute window.

Is there a fix to port? No. #5274 (merged) touched the C6 gate's comment text and issue refs, not this timeout, and no open PR addresses it. I am deliberately not widening this supply-chain PR to change MAX_WAIT or the gate's pending-leg semantics — that is a real decision about how long the gate should tolerate a slow queue, and it belongs in its own change.

What I am doing: re-running the gate once, after the CI run finishes, so it re-reads the check states with Entitlement API tests settled. If it goes green, this is closed. If it times out again with the suite genuinely hung rather than merely late, that is a pre-existing Entitlement API tests problem on main and wants its own issue — worth noting that this run's suite step has been executing far longer than the 8m41s the same job took on #5275, which is the one thing here that may be more than queue congestion.


Generated by Claude Code

Copy link
Copy Markdown
Owner Author

Resolved as diagnosed. Entitlement API tests finished green at 04:11:45 — its suite took 13m08s and completed 1m47s after the gate's 1800s budget expired at 04:09:58. Nothing was hung and nothing failed; the job simply started late behind a congested runner queue.

The single re-run of E2E Gate (required) then passed in 12 seconds (attempt 2), because it re-read the same check states with that last leg settled. All 19 CI jobs green, mergeable_state: clean.

No code change was needed or made. The standing observation from the previous comment: this gate has now timed out on main several times, and a required check that goes red purely on runner-queue latency will keep costing re-runs — worth its own change to the wait budget or the pending-leg semantics, separate from this PR.


Generated by Claude Code

@vivekchand
vivekchand merged commit e64bb34 into main Aug 28, 2026
36 of 37 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