Skip to content

ci: declare read-only GitHub token permissions for workflows - #265

Merged
karagozemin merged 1 commit into
Sub-Rosa-Issue:mainfrom
leocagli:ci/read-only-token-permissions
Aug 30, 2026
Merged

ci: declare read-only GitHub token permissions for workflows#265
karagozemin merged 1 commit into
Sub-Rosa-Issue:mainfrom
leocagli:ci/read-only-token-permissions

Conversation

@leocagli

Copy link
Copy Markdown

Closes #249

Every workflow now declares contents: read at workflow level. Nothing else changed.

What was there before

None of the four workflows declared a permissions block, so all four inherited the repository default, which is broader than what these jobs use:

workflow before after
bindings-check.yml inherited default contents: read
contract.yml inherited default contents: read
coverage.yml inherited default contents: read
docs-links.yml inherited default contents: read

Why contents: read is enough

I checked this before lowering anything, since a workflow that actually writes would break on its next run rather than at merge time. Across all four workflows there is:

  • no git push, no gh pr / gh issue / gh release
  • no reference to GITHUB_TOKEN and no secrets.*
  • no deploy or pages-upload step

The complete set of actions used is actions/checkout@v4, actions/setup-node@v4, pnpm/action-setup@v4, dtolnay/rust-toolchain@stable and Swatinem/rust-cache@v2. All read-only.

Placement and validation

The block goes after the on: section and before the next top-level key, so it reads where a reviewer expects it.

All four parse after the change, with triggers and jobs unchanged:

bindings-check.yml  permissions={'contents': 'read'}  jobs=['check']          triggers=['push', 'pull_request']
contract.yml        permissions={'contents': 'read'}  jobs=['round-contract'] triggers=['push', 'pull_request']
coverage.yml        permissions={'contents': 'read'}  jobs=['coverage']       triggers=['push', 'pull_request']
docs-links.yml      permissions={'contents': 'read'}  jobs=['check-links']    triggers=['push', 'pull_request']

One thing worth knowing for later

This makes the workflow-level grant explicit, so any future job that needs to write (commenting on a PR, pushing bindings, publishing) will have to declare its own job-level permissions. That is the intended trade: it fails loudly at the job that needs it instead of quietly having write access everywhere.

No action versions, triggers, job names or commands were touched.

🤖 Generated with Claude Code

Closes Sub-Rosa-Issue#249

Los cuatro workflows heredaban los permisos por defecto del repositorio en
vez de declarar el minimo que usan. Ahora los cuatro declaran
`contents: read` a nivel workflow.

Verificado antes de tocar nada: ninguno de los cuatro hace push, comenta,
publica releases ni referencia GITHUB_TOKEN o secrets. Las unicas acciones
que usan son checkout, setup-node, pnpm/action-setup, rust-toolchain y
rust-cache, todas de solo lectura. Asi que bajar el permiso no le saca nada
a ningun job.

Sin cambios de triggers, de jobs, de versiones de acciones ni de comandos.
Los cuatro YAML siguen parseando.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.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: declare read-only GitHub token permissions for workflows

2 participants