Skip to content

fix(ci): harden GitHub Actions workflows (#1221) - #1228

Merged
paulinebm merged 1 commit into
mainfrom
security/workflow-hardening/pr-1221
Sep 22, 2026
Merged

paulinebm merged 1 commit into
mainfrom
security/workflow-hardening/pr-1221

Conversation

@hf-security-analysis

@hf-security-analysis hf-security-analysis Bot commented Sep 22, 2026 •

Copy link
Copy Markdown
Contributor

Automated hardening of the workflow files flagged on #1221.

Targets main. Files changed, and what changed them:

  • .github/workflows/publish-pypi.yml — action pins
  • .github/workflows/publish-testpypi.yml — action pins

Fixed by this PR:

  • HIGH unpinned-action (pinact) — .github/workflows/publish-pypi.yml:31
  • HIGH unpinned-action (pinact) — .github/workflows/publish-pypi.yml:69
  • HIGH unpinned-action (pinact) — .github/workflows/publish-pypi.yml:101
  • HIGH unpinned-action (pinact) — .github/workflows/publish-pypi.yml:120
  • HIGH unpinned-action (pinact) — .github/workflows/publish-pypi.yml:139
  • HIGH unpinned-action (pinact) — .github/workflows/publish-pypi.yml:172
  • HIGH unpinned-action (pinact) — .github/workflows/publish-testpypi.yml:34
  • HIGH unpinned-action (pinact) — .github/workflows/publish-testpypi.yml:39
  • HIGH unpinned-action (pinact) — .github/workflows/publish-testpypi.yml:116
  • HIGH unpinned-action (pinact) — .github/workflows/publish-testpypi.yml:135

This does not fix everything. 2 further finding(s) (2 high) need a decision this bot should not make for you. They are in the security channel with their locations — deliberately not repeated here, since this repository may be public and they are not fixed yet.

Pinning changes come from pinact and are mechanical. Any other change was generated by Claude — read it before merging.


Note

Low Risk
Mechanical action pinning only; publish behavior is unchanged, though some release workflow actions may still be unpinned outside this diff.

Overview
Pins third-party GitHub Actions in the PyPI and TestPyPI release workflows to immutable commit SHAs (with version comments), replacing floating refs like @v7 and @v8.

Affected steps include checkout, setup-python, upload-artifact, and download-artifact in publish-pypi.yml (build, publish, GitHub release, and post-release bump jobs) and the matching build/publish jobs in publish-testpypi.yml. Workflow logic and release steps are unchanged; this is supply-chain hardening from pinact.

Note: pypa/gh-action-pypi-publish@release/v1 is still tag-based in both workflows (called out separately in #1221 as not addressed here).

Reviewed by Cursor Bugbot for commit d21c273. Bugbot is set up for automated code reviews on this repo. Configure here.

@burtenshaw burtenshaw added bug Something isn't working size: small Small pull request labels Sep 22, 2026 — with Cursor
@bot-ci-comment

Copy link
Copy Markdown

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.

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Alignment Review Report

Scope: mechanical supply-chain hardening — pins GitHub Actions to full commit SHAs (with version comments) in .github/workflows/publish-pypi.yml and .github/workflows/publish-testpypi.yml. No Python or runtime code is touched.

Automated Checks

  • Lint: FAIL (hook exit 1) — not attributable to this PR. In this fresh environment the hook builds a new .venv and resolves ruff 0.16.8 (repo pins ruff>=0.14.0), which then reports 56 pre-existing Python files under src/, tests/, and envs/ as "would reformat". ruff/usort do not process YAML, and this PR changes only workflow .yml files, so it introduces zero lint findings.
  • Debug code: CLEAN for this PR. check-debug.sh flags only pre-existing print/TODO items in src/ (CLI, harbor, docstring examples); none are in the two changed workflow files.

Open RFCs Context

All RFCs are Draft or In Review (000, 001, 002, 003, 004, 005, 008, 010, 011, 012), but every one concerns environment/runtime design (abstractions, env-spec, MCP, rubrics, agentic harnesses, auto-validation, echo-env, catalog discovery, harbor capture). None govern CI/CD or GitHub Actions, so none are relevant to this change.

Tier 1: Fixes Required

None. I independently verified every pin against authoritative GitHub tag data (git/ref/tags, dereferencing annotated tags to commits):

Action Pinned SHA Comment Result
actions/checkout 3d3c42e…90b1 v7.0.1 MATCH
actions/setup-python 5fda3b9…4b97 v7.0.0 MATCH
actions/upload-artifact 043fb46…6a0a v7.0.1 MATCH
actions/download-artifact 3e5f45b…1e7c v8.0.1 MATCH

The floating major tags that were replaced (checkout@v7, setup-python@v7, download-artifact@v8) currently resolve to exactly these SHAs, so the pins are behavior-preserving; version comments are accurate. This is consistent with the "No credential exposure" security invariant and the existing persist-credentials: false on checkout. No syntax errors, no secrets, no debug code introduced.

Tier 2: Alignment Discussion

Principle Conflicts

None identified. The change is CI-only and engages none of the runtime principles/invariants (Gymnasium API, client-server separation, rewards-in-environment, MCP/WebSocket dual boundary, container isolation).

RFC Conflicts

None identified.

Informational (non-blocking follow-ups)

  • pypa/gh-action-pypi-publish@release/v1 remains a moving branch ref in both publish workflows — the most trust-sensitive step, since it performs the actual PyPI publish. The PR description already acknowledges this is tracked separately and intentionally left for a human decision. Noted, not a blocker.
  • Several other workflows still use floating action tags (e.g. docker-build.yml, openspiel_base_build.yml, test.yml, package-ci.yml, deploy-hf-env.yml, manage-hf-collection.yml), including third-party docker/* and astral-sh/setup-uv. These are out of scope for this PR (which targets only the two flagged files); a follow-up could extend the same pinact pinning repo-wide.

Summary

  • 0 mechanical issues to fix (Tier 1)
  • 0 alignment points for human review (Tier 2)
  • 0 RFC conflicts to discuss

Verdict: correct, verified, behavior-preserving CI hardening. The only items are two acknowledged, out-of-scope follow-ups noted above.

Open in Web View Automation 

Sent by Cursor Automation: Pre-review

@cursor cursor Bot mentioned this pull request Sep 22, 2026
21 tasks

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Content review at d21c2734. This supersedes #1224, which GitHub auto-closed when I merged its base #1221. Same branch, same tree, but now correctly based on main, so it will actually run Tests, Package CI, and lint — none of which could run while the base was a Dependabot branch.

Pins verified against upstream

Action Pinned SHA Resolves to
actions/checkout 3d3c42e5aac5ba805825da76410c181273ba90b1 v7.0.1
actions/setup-python 5fda3b95a4ea91299a34e894583c3862153e4b97 v7.0.0
actions/upload-artifact 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a v7.0.1
actions/download-artifact 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c v8.0.1

I resolved each tag through the GitHub API; all four match. The diff is confined to publish-pypi.yml and publish-testpypi.yml and is purely mechanical tag-to-SHA replacement across ten uses: lines. No job, trigger, permission, environment, or secret binding changes, and the v7.0.1 upload-artifact pin from #1221 is preserved.

Needs a decision I should not make

Both pypa/gh-action-pypi-publish@release/v1 invocations remain on a mutable branch ref. Those are the two jobs holding id-token: write against the PyPI and TestPyPI Trusted Publishers, so they are the most security-sensitive refs in the repository and the two findings the bot still reports as HIGH. Pinning them is a release-credential boundary decision and needs the release owner, against a specific reviewed commit rather than the moving branch. I have requested @burtenshaw as reviewer for that reason.

Recommended timing: merge after Thursday's v0.6.0 publish, not before.

The 0.6.0 candidate has already been validated end to end through publish-testpypi.yml as it stands on main today, including a real TestPyPI upload with upload-artifact@v7.0.1. Landing this now would change the publish path after that validation and leave no cycle to re-exercise it before the release. Merging immediately afterwards gives these pins a full TestPyPI run before they matter, and there is no urgency in the gap: every ref this PR replaces is an official major-version tag, not a third-party one.

The branch is currently BEHIND main; it needs a refresh and terminal green CI before it is mergeable either way.

Open in Web View Automation 

Sent by Cursor Automation: Release

@cursor
cursor Bot requested a review from burtenshaw September 22, 2026 06:33
@paulinebm
paulinebm merged commit 43aa752 into main Sep 22, 2026
13 checks passed
cursor Bot pushed a commit that referenced this pull request Sep 22, 2026
Pauline merged pinact harden #1228; keep draft #1211 exact-main.

Co-authored-by: benjamin.burtenshaw <benjamin.burtenshaw@huggingface.co>
cursor Bot added a commit that referenced this pull request Sep 24, 2026
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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size: small Small pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants