Skip to content

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

Closed
hf-security-analysis[bot] wants to merge 0 commit into
dependabot/github_actions/actions/upload-artifact-7.0.1from
security/workflow-hardening/pr-1221
Closed

hf-security-analysis[bot] wants to merge 0 commit into
dependabot/github_actions/actions/upload-artifact-7.0.1from
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 dependabot/github_actions/actions/upload-artifact-7.0.1. 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
Changes are limited to CI workflow action pins with no application or release-logic edits.

Overview
Hardens PyPI release CI by pinning third-party GitHub Actions in publish-pypi.yml and publish-testpypi.yml, addressing pinact unpinned-action findings on the checkout, setup-python, upload-artifact, and download-artifact steps (including actions/upload-artifact@v7.0.1 on the artifact upload steps).

Pin updates are mechanical from pinact; behavior of the publish/TestPyPI pipelines should stay the same while reducing supply-chain risk from floating action refs. Two high-severity workflow findings called out in #1221 are still open and are not part of this diff.

Reviewed by Cursor Bugbot for commit 48a767d. 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: 2 files — .github/workflows/publish-pypi.yml and .github/workflows/publish-testpypi.yml. The PR pins four actions/* steps from mutable tags to full-length commit SHAs (with version comments). No Python / library code is touched.

Automated Checks

  • Lint: PASS for this PR's scope. ruff format --check → 337 files already formatted; ruff check → all checks passed. usort check flags only two pre-existing files (tests/envs/test_grid_world.py, tests/envs/test_julia_env.py) that are known-flagged on a clean tree and unrelated to this PR (which changes no Python).
  • Debug code: CLEAN. The debug-scan hits are all pre-existing docstring / CLI / manual-test code under src/; none are in the files this PR touches.

Independent SHA verification

Because this PR is from an automated author and pins to opaque SHAs, I resolved each claimed tag against the official upstream repo (GET /repos/<action>/commits/<tag>). All four match exactly, and each also equals what the mutable tag it replaced currently points to — so this is a faithful pin with no version drift:

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

The surrounding hardening in these workflows is already solid (permissions: contents: read by default, least-privilege per-job perms, persist-credentials: false, PyPI Trusted Publisher via OIDC, tag/version validation).

Open RFCs Context

No RFC covers CI / GitHub Actions / release workflows, so none are in conflict. (In Review: 000, 001, 002, 003, 005, 008, 012; Draft: 010, 011.)

Tier 1: Fixes Required

None. The change is mechanically correct and the SHAs + version comments are accurate.

Tier 2: Alignment Discussion

Principle Conflicts — None identified. OpenEnv's principles/invariants govern the env/client/server architecture (Gym API, MCP agent boundary, rewards-in-environment, client-server separation); this CI-only change doesn't touch any of them.

RFC Conflicts — None identified.

Non-blocking observations

  1. Scope vs. title. The title says "harden GitHub Actions workflows (#1221)" but only the two publish workflows are pinned. Several others still use mutable tags: docker-build.yml, openspiel_base_build.yml, deploy-hf-env.yml, package-ci.yml, manage-hf-collection.yml, test.yml (e.g. actions/checkout@v7, docker/*@v4/v6/v7, astral-sh/setup-uv@v7). Prioritizing the publish workflows first is reasonable — they hold the most sensitive permissions (PyPI OIDC id-token: write, contents: write, pull-requests: write) — but consider a follow-up to cover the rest for a consistent posture, and confirm the reduced scope matches the intent of #1221.
  2. pypa/gh-action-pypi-publish@release/v1 is intentionally left as a branch ref (PyPA's recommended usage for the trusted-publisher flow). Fine to leave as-is; a strict pin-everything policy would also pin it to a SHA.

Summary

  • 0 mechanical issues to fix
  • 0 alignment points for human review
  • 0 RFC conflicts to discuss
  • Verdict: clean, correct security hardening — all four pinned SHAs independently verified against upstream. Only a non-blocking scope/completeness note for follow-up.
Open in Web View Automation 

Sent by Cursor Automation: Pre-review

@hf-security-analysis
hf-security-analysis Bot force-pushed the security/workflow-hardening/pr-1221 branch from f0ca9a5 to 48a767d Compare September 22, 2026 06:13

@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.

This PR was auto-closed as collateral when I merged its base, and it should be restored.

It targeted dependabot/github_actions/actions/upload-artifact-7.0.1 rather than main. When #1221 merged as ca4219d2, GitHub deleted that base branch and closed this PR instead of retargeting it. That was my merge, not an author decision, and it is not a verdict on the change.

The head branch survives: security/workflow-hardening/pr-1221 at d21c2734. Reopening it and retargeting to main restores the PR with full history; both reopenPullRequest and updatePullRequest are 403 for this token, so I cannot do it myself. Retargeting to main also has a real benefit: this PR never ran the repository Tests, Package CI, or lint workflows, because those only trigger on PRs whose base is main. Only Build PR Documentation, Bugbot, and the automation checks ran here.

What I verified in the content (all still valid)

Every pin resolves to the official tag it claims:

Action Pinned SHA Tag
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

The diff is mechanical: it only replaces mutable major-version tags with those immutable SHAs in publish-pypi.yml and publish-testpypi.yml. No job, permission, trigger, or environment binding changes.

What still needs a human decision

Both pypa/gh-action-pypi-publish@release/v1 invocations stay on a mutable branch ref. Those are exactly the jobs that hold id-token: write against the PyPI and TestPyPI Trusted Publishers, so they are the highest-value refs in the repository to pin and the two the security bot still reports as HIGH. Pinning them is a release-credential boundary decision, so I am not making it: it needs the release owner, and it needs a reviewed commit rather than the moving release/v1 branch.

Recommendation on timing. Restore the PR now, but land it after Thursday's v0.6.0 publish rather than before. The 0.6.0 candidate has already been validated end-to-end through publish-testpypi.yml as it stands today, including the upload-artifact@v7.0.1 pin from #1221. Landing this immediately would change the publish path again after that validation, with no time to re-exercise it. Merging right after the release gives the pins a full TestPyPI cycle before they matter.

Open in Web View Automation 

Sent by Cursor Automation: Release

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.

1 participant