Pin GitHub Actions to commit SHAs - #1240
Conversation
A tag is mutable: whoever controls the action's repository can move `v4` to different code, and the next run picks it up with no diff to review. Pinning to the commit SHA freezes the code that runs today.
|
The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update. |
There was a problem hiding this comment.
APPROVE at 81a4ce15
Pin-not-upgrade: mutable @vN tags → immutable commit SHAs with version comments. Does not touch publish-pypi.yml / publish-testpypi.yml (already SHA-pinned on main). Checkout/setup-python SHAs match what those publish workflows already use (3d3c42e5…, 5fda3b95…). No package cargo.
Timing: prefer merge after tomorrow’s v0.6.0 tag so PR CI (test.yml / package-ci.yml) doesn’t churn on the release day path. Safe either way — claimed SHAs are today’s tag tips.
Sent by Cursor Automation: Release
There was a problem hiding this comment.
Alignment Review Report
Mechanical, repo-wide SHA-pin of GitHub Actions across 6 workflow files (deploy-hf-env, docker-build, manage-hf-collection, openspiel_base_build, package-ci, test). 7 distinct actions, all floating major tags → full 40-char commit SHAs annotated # vX.Y.Z. Verdict: security-positive, nothing blocking.
Automated Checks
- Lint: PASS (N/A to diff) — the lint hook only covers Python (
src/ tests/ envs/) and never touches.github/workflows/; a YAML-only diff introduces no lint surface. (Pre-existingenvs/**reformat noise is unrelated to this PR.) - Debug code: CLEAN —
check-debug.shscanssrc/only; every hit it reports (harbor/*,cli/*,core/mcp_client.py, …) is pre-existing and outside this PR's changed files. Zero debug code in the diff.
Open RFCs Context
Current rfcs/: 000/001/002/003/005/008/012 (In Review), 004 (Rubrics, no status header), 010/011 (Draft). None govern CI, GitHub Actions, or action/dependency pinning — no RFC surface for this change.
Tier 1: Fixes Required
None. I verified every pin against the GitHub API: each SHA equals its claimed # vX.Y.Z tag and equals the current tip of the floating major tag it replaces — i.e. zero behavioral change at merge, exactly as the PR body states ("this pins, it does not upgrade").
| Action | Pinned SHA | Tag | SHA==tag | == @major tip |
|---|---|---|---|---|
| actions/checkout | 3d3c42e5… |
v7.0.1 | ✅ | ✅ (v7) |
| actions/setup-python | 5fda3b95… |
v7.0.0 | ✅ | ✅ (v7) |
| astral-sh/setup-uv | 37802adc… |
v7.6.0 | ✅ | ✅ (v7) ¹ |
| docker/setup-buildx-action | f87e5991… |
v4.4.1 | ✅ | ✅ (v4) |
| docker/login-action | dbcb8138… |
v4.6.0 | ✅ | ✅ (v4) |
| docker/metadata-action | dc802804… |
v6.2.0 | ✅ | ✅ (v6) |
| docker/build-push-action | c3c9e263… |
v7.4.0 | ✅ | ✅ (v7) |
YAML parses cleanly for all 6 files; git merge-tree against main is conflict-free.
Tier 2: Alignment Discussion
Principle Conflicts
None identified. SHA-pinning is security-positive and reinforces the reproducibility posture (PRINCIPLES.md) and the "No credential exposure" invariant (INVARIANTS.md). The affected jobs authenticate via secrets.* / GHCR login / OIDC, and package-ci.yml already sets persist-credentials: false; freezing action code cuts supply-chain risk (the exact tj-actions/changed-files class of attack the PR body cites) without adding any credential or injection surface. PRINCIPLES/INVARIANTS govern the runtime API (Gym/MCP/rewards/client-server/container isolation) — untouched here.
RFC Conflicts
None identified. No RFC covers CI / GitHub Actions.
Summary
- 0 mechanical issues to fix
- 0 alignment points for human review
- 0 RFC conflicts
Notes (non-blocking):
¹ astral-sh/setup-uv is pinned to v7.6.0, the tip of the repo's floating @v7. setup-uv's latest overall is v10.2.0 — this is not a defect: the PR correctly preserves the existing major (v7→v10 would be a separate, deliberate upgrade, and the repo intentionally tracks setup-uv @v7).
- Completeness: after this PR, the only remaining floating (non-SHA) action ref in the whole
.github/workflows/tree ispypa/gh-action-pypi-publish@release/v1(publish-pypi.yml:128,publish-testpypi.yml:143— both untouched here). Prior hardening PRs (#1227 / #1228) already flagged that trusted-publisher branch ref as intentionally deferred to a human decision, so this PR sensibly leaves it alone and effectively completes the repo-wide pinning pass those PRs started.
Suggested reviewers: @burtenshaw (owns the CI workflows + .github/dependabot.yml); cc @sergiopaniego (last human author of docker-build.yml and openspiel_base_build.yml).
Sent by Cursor Automation: Pre-review
|
|
||
| - name: Set up Docker Buildx | ||
| uses: docker/setup-buildx-action@v4 | ||
| uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1 |
There was a problem hiding this comment.
Verified the four third-party Docker action pins here (the highest supply-chain sensitivity) against the GitHub API — each matches its # vX.Y.Z comment and the current tip of the @major tag it replaced, so they're behavior-preserving:
docker/setup-buildx-actionf87e5991…= v4.4.1 (@v4tip)docker/login-actiondbcb8138…= v4.6.0 (@v4tip)docker/metadata-actiondc802804…= v6.2.0 (@v6tip)docker/build-push-actionc3c9e263…= v7.4.0 (@v7tip)
The same four pins are applied identically in openspiel_base_build.yml. ✅
|
|
||
| - name: Install uv | ||
| uses: astral-sh/setup-uv@v7 | ||
| uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0 |
There was a problem hiding this comment.
astral-sh/setup-uv 37802adc… = v7.6.0, verified == the tip of the repo's floating @v7.
Heads-up for reviewers: setup-uv's latest release overall is v10.2.0, so this can read as "behind" — but it's correct here. The PR preserves the pinned major (v7); moving to v10 is a separate deliberate upgrade decision. actions/checkout@… = v7.0.1 on line 27 is likewise verified == @v7 tip. ✅
| steps: | ||
| - name: Checkout code | ||
| uses: actions/checkout@v7 | ||
| uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 |
There was a problem hiding this comment.
First-party pins verified: actions/checkout 3d3c42e5… = v7.0.1 and actions/setup-python 5fda3b95… = v7.0.0 (line 30) — both == their tag == @v7 tip. Nice that this checkout already sets persist-credentials: false; SHA-pin + no-persist is a solid supply-chain combination. ✅
Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
OpenEnv 0.6.0 Breaking change - `--llm-endpoint` / OpenAIClient now take a full base URL; the implicit port 8000 is gone. `http://localhost` means port 80; use `http://localhost:8000` or `--llm-port 8000` for the old behavior (#1189, landed via #1237). New - NovitaSandboxProvider: run an OpenEnv server in a Novita AI sandbox over wss://, from a registry image or a local Dockerfile; install with `pip install openenv[novita]` (#1191). - RFC 008 Level 2 validation building blocks: manifest-v2, report-v2 and runtime-plan schemas, the severity-v2 policy, and DockerValidationProvider (#1178, #1179). The `openenv validate` CLI is unchanged in this release. Fixes - A failed `new_session()` no longer leaves the provider's container or sandbox running (#1145). Repository and environment images (not in the wheel) - coding_env `additional_imports` now extends the default safe-import allowlist (#1147). - Environment lockfile security updates: anyio 4.14.2 and soupsieve 2.9.2 (#1196, #1197, #1201, #1202). - CI hardening: per-job GITHUB_TOKEN scopes and SHA-pinned actions (#1221, #1223, #1225, #1226, #1228, #1239, #1240); validation-lab toolchain pins (#1229, #1230, #1231); docs navigation and Miles integration docs (#1219, #1220). Known, accepted for this release: Novita provider debt (unbraced $ARG ordering in Dockerfile flattening, a tbench2 example readiness leak); fixes follow in #1235. Validated: exact-head CI 13/13 on 0034202; TestPyPI 0.6.0.dev141 (run 35854754769) byte-identical to the release wheel apart from Version; clean wheel/sdist install, CLI, and Echo reset/step smoke.


Workflow hardening
Actions pinned to commit SHAs
A version tag is mutable. Whoever controls an action's repository can move
v4to different code, and every workflow referencing
@v4picks that up on thenext run with nothing to review. That is how
tj-actions/changed-filesshippeda credential dumper to thousands of repositories in March 2025.
Pinning to a full commit SHA freezes the code that runs. The version tag stays
on the line as a comment, so the reference is still readable.
This pins, it does not upgrade. Every SHA below is the commit the tag
already resolves to today, so nothing about what your CI executes changes — it
only removes the ability for it to change without your knowing.
.github/workflows/deploy-hf-env.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/deploy-hf-env.ymluses: actions/setup-python@v7uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0.github/workflows/docker-build.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/docker-build.ymluses: docker/setup-buildx-action@v4uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1.github/workflows/docker-build.ymluses: docker/login-action@v4uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0.github/workflows/docker-build.ymluses: docker/metadata-action@v6uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0.github/workflows/docker-build.ymluses: docker/build-push-action@v7uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0.github/workflows/docker-build.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/docker-build.ymluses: docker/setup-buildx-action@v4uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1.github/workflows/docker-build.ymluses: docker/login-action@v4uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0.github/workflows/docker-build.ymluses: docker/metadata-action@v6uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0.github/workflows/docker-build.ymluses: docker/build-push-action@v7uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0.github/workflows/manage-hf-collection.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/manage-hf-collection.ymluses: actions/setup-python@v7uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0.github/workflows/openspiel_base_build.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/openspiel_base_build.ymluses: docker/setup-buildx-action@v4uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1.github/workflows/openspiel_base_build.ymluses: docker/login-action@v4uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0.github/workflows/openspiel_base_build.ymluses: docker/metadata-action@v6uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0.github/workflows/openspiel_base_build.ymluses: docker/build-push-action@v7uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0.github/workflows/openspiel_base_build.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/openspiel_base_build.ymluses: docker/setup-buildx-action@v4uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1.github/workflows/openspiel_base_build.ymluses: docker/login-action@v4uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0.github/workflows/openspiel_base_build.ymluses: docker/metadata-action@v6uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0.github/workflows/openspiel_base_build.ymluses: docker/build-push-action@v7uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0.github/workflows/package-ci.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/package-ci.ymluses: actions/setup-python@v7uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0.github/workflows/test.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/test.ymluses: astral-sh/setup-uv@v7uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0.github/workflows/test.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/test.ymluses: astral-sh/setup-uv@v7uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0.github/workflows/test.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/test.ymluses: astral-sh/setup-uv@v7uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0.github/workflows/test.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/test.ymluses: actions/setup-python@v7uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0.github/workflows/test.ymluses: actions/checkout@v7uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1.github/workflows/test.ymluses: astral-sh/setup-uv@v7uses: astral-sh/setup-uv@37802adc94f370d6bfd71619e3f0bf239e1f3b78 # v7.6.0Note
Low Risk
Workflow-only supply-chain hardening with no application code changes; pinned SHAs correspond to the previously referenced tag versions.
Overview
Replaces mutable
@v*action references with immutable commit SHAs across six workflows (deploy-hf-env,docker-build,manage-hf-collection,openspiel_base_build,package-ci, andtest). Each line keeps the former tag as an inline comment (e.g.# v7.0.1) so upgrades stay readable.Affected third-party actions include
actions/checkout,actions/setup-python,astral-sh/setup-uv, and the Docker build/login/metadata/build-push stack. Behavior should be unchanged—the SHAs match what those tags already pointed at; the goal is to stop tag retags from silently changing CI on the next run.Reviewed by Cursor Bugbot for commit 81a4ce1. Bugbot is set up for automated code reviews on this repo. Configure here.