Skip to content

ci: pin actions and scope workflow token permissions - #95

Merged
CodewithJha merged 1 commit into
CodewithJha:mainfrom
Sonike:fix/pin-actions-and-limit-permissions
Oct 6, 2026
Merged

CodewithJha merged 1 commit into
CodewithJha:mainfrom
Sonike:fix/pin-actions-and-limit-permissions

Conversation

@Sonike

@Sonike Sonike commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes #64 (MUT-013). Related: #20 remains the separate Dependabot/CODEOWNERS task.

  • Pin all 11 Action references in CI, publishing, and the contributor gallery to verified commits in their official upstream repositories, with release comments: checkout v4.4.0, setup-uv v5.4.2, and setup-node v4.4.0. These are the commits currently selected by the existing major tags; this does not change their major versions.
  • Default each workflow to contents: read. Keep id-token: write only on the existing PyPI publishing job. Move contents: write from the contributors workflow default to its gallery job, where it is required for the existing README commit/push. That job still has write access; this change does not replace its direct-push design.
  • Disable persisted checkout credentials in CI and publishing. Retain them for the gallery's final push. Only the three workflow YAML files change; jobs, triggers, matrices, cache configuration, build/test commands, and publishing commands remain intact.

This follows GitHub's guidance on immutable Action references and minimum token permissions. The pin mappings were checked against the official repository commit/tag APIs before submission.

Type of change

  • Docs / community / DX only
  • Bug fix

Checklist

  • Read CONTRIBUTING.md and linked the related issue.
  • Core stays free of framework SDK imports; no application code changes.
  • Verified the changed workflow contracts and ran existing tests.
  • Docs / README claims match reality.
  • One concern; authorized testing only.

Test plan

  • actionlint 1.7.12 over all three workflows: passed (-shellcheck=''; shell commands are unchanged).
  • External YAML check: all 11 references are full 40-character SHAs; effective permissions are read-only for CI, read plus OIDC for publish, and contents-write only for the gallery job; checkout credentials are disabled where no push is needed. Normalizing only those intended changes gives the same triggers, jobs, matrices, and commands as the base. The same check reports the original floating references and broad/missing defaults on the base.
  • uv run --offline pytest tests/unit tests/integration tests/reliability -q --tb=short: 632 passed on Python 3.12.13.
  • Real offline sample: mutiny --help, mutiny init, and mutiny run completed successfully.
  • npm ci, npx tsc --noEmit, and npm run build: passed. npm reports 12 existing dependency audit findings (11 high, 1 critical); the lockfile and application dependencies are unchanged.
  • scripts/verify_release_artifacts.sh: passed, including wheels/sdists, isolated installation, offline CLI, and database backup/restore.
  • git diff --check: passed.

No PyPI upload or contributor-gallery push was performed. Their required job permissions are preserved and statically checked. GitHub-hosted CI results are separate from these local checks.

Prepared with Codex; the workflow diff and validation results were reviewed before submission.

@vercel

vercel Bot commented Oct 6, 2026

Copy link
Copy Markdown

@Sonike is attempting to deploy a commit to the priyanshu's projects Team on Vercel.

A member of the Team first needs to authorize it.

@CodewithJha CodewithJha left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Verified locally and on CI. All 11 uses: refs are pinned to the exact commits behind checkout v4.4.0, setup-uv v5.4.2, and setup-node v4.4.0 (checked with git ls-remote against upstream), so the pinning causes no behavior drift. actionlint is clean. 632 tests pass. Permissions now meet every #64 acceptance criterion, and #20 is correctly left alone.

@CodewithJha
CodewithJha merged commit fdf815c into CodewithJha:main Oct 6, 2026
5 of 6 checks passed
@CodewithJha

Copy link
Copy Markdown
Owner

Merged, thank you @Sonike. This is a careful supply-chain fix:

  • Every action is pinned to the exact commit its current major tag resolves to. That closes the floating-tag risk without changing which code runs.
  • The contents: write grant moved from the contributors workflow default to the one job that pushes. CI and publish now default to read-only, and id-token: write stays only on the PyPI job.
  • persist-credentials: false everywhere except the gallery push, with a comment explaining the exception.
  • A clear test plan: actionlint, the static permission check, and a full release-artifact run.

Closes #64 (MUT-013). If you want a next one in this area:

CodewithJha pushed a commit that referenced this pull request Oct 6, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
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.

[CI] MUT-013: Unpin GitHub Actions and missing CI least-privilege permissions

2 participants