Skip to content

chore(ci): harden workflow permissions and gate releases to owner#211

Merged
stormslowly merged 2 commits into
mainfrom
chore/harden-workflow-permissions
May 13, 2026
Merged

chore(ci): harden workflow permissions and gate releases to owner#211
stormslowly merged 2 commits into
mainfrom
chore/harden-workflow-permissions

Conversation

@stormslowly
Copy link
Copy Markdown
Collaborator

@stormslowly stormslowly commented May 12, 2026

Summary

Tighten GITHUB_TOKEN exposure across every workflow.

Changes

Minimum-privilege permissions: blocks

Workflow Before After
ci.yml (default, repo setting decides) top-level contents: read
benchmark.yml (default) top-level contents: read
codecov.yml (default) top-level contents: read
reusable-build.yml top-level issues: write (unused — no step touches issues) top-level contents: read
release-npm.yml top-level id-token: write + issues: write (broadcast to every job) top-level permissions: {}; build matrix gets contents: read; release job gets contents: write + id-token: write
release-plz.yml top-level id-token: write + contents: write top-level permissions: {}; release-plz job gets the two grants it actually needs

The principle is: the default token starts at nothing, and each job earns only the scope its steps actually use. This blocks an exploit running in (say) a build matrix runner from upgrading the cached repo token to a publish credential or comment-on-issues credential.

Test plan

  • All non-release workflows (ci, benchmark, codecov) pass with the new read-only default token
  • release-plz and release-npm dispatch runs still publish successfully (verified next time we cut a release)
  • reusable-build.yml build matrix continues to succeed under contents: read

Tighten GITHUB_TOKEN exposure on every workflow:

- ci.yml, benchmark.yml, codecov.yml: add top-level
  permissions: contents: read so PRs run on a read-only token.
- reusable-build.yml: drop the unused issues: write grant (no step
  in this file touches issues) and downgrade to contents: read.
- release-npm.yml, release-plz.yml: collapse top-level permissions to
  empty and grant the minimum each job actually needs (id-token: write
  for OIDC provenance, contents: write only on jobs that push tags).

Add a repository_owner == rstackjs guard to all release jobs as a
belt-and-suspenders check on top of workflow_dispatch + environment
reviewers, so a fork that ever fires a workflow_dispatch (or a future
trigger change) can't proceed.
Copilot AI review requested due to automatic review settings May 12, 2026 08:45
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab7730b98c

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread .github/workflows/ci.yml
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR hardens GitHub Actions security posture by enforcing least-privilege GITHUB_TOKEN permissions across workflows and adding a defensive owner-only guard for release workflows, reducing blast radius if a job is compromised.

Changes:

  • Add explicit permissions: blocks to default to contents: read (or {} where appropriate) instead of relying on repository defaults.
  • Scope elevated permissions (contents: write, id-token: write) to only the specific release jobs that need them.
  • Gate release-related jobs with if: github.repository_owner == 'rstackjs' to prevent unintended execution outside the canonical repo.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated no comments.

Show a summary per file
File Description
.github/workflows/reusable-build.yml Drops broad permissions and restricts the reusable build workflow to contents: read.
.github/workflows/release-plz.yml Sets default token permissions to none and grants id-token: write + contents: write only to the release job; adds owner guard.
.github/workflows/release-npm.yml Sets default token permissions to none; grants contents: read to build matrix and contents: write + id-token: write only to release job; adds owner guard.
.github/workflows/codecov.yml Adds top-level contents: read to avoid implicit default permissions.
.github/workflows/ci.yml Adds top-level contents: read to avoid implicit default permissions.
.github/workflows/benchmark.yml Adds top-level contents: read to avoid implicit default permissions.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented May 12, 2026

Merging this PR will not alter performance

✅ 12 untouched benchmarks


Comparing chore/harden-workflow-permissions (15d2a61) with main (4574c84)

Open in CodSpeed

The guard is unnecessary because npm and crates.io trusted publishing
already pin the OIDC token's repository claim. A fork that fires these
workflow_dispatch workflows would mint a token for its own repo and be
rejected by both registries' publisher allowlists, so the guard adds
no real protection while adding noise.
@stormslowly stormslowly merged commit 64a7440 into main May 13, 2026
21 checks passed
@stormslowly stormslowly deleted the chore/harden-workflow-permissions branch May 13, 2026 06:35
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.

3 participants