Skip to content

ci: set a least-privilege default GITHUB_TOKEN scope - #1831

Merged
cliffhall merged 1 commit into
mainfrom
fix/1817-workflow-token-permissions
Jul 28, 2026
Merged

ci: set a least-privilege default GITHUB_TOKEN scope#1831
cliffhall merged 1 commit into
mainfrom
fix/1817-workflow-token-permissions

Conversation

@cliffhall

Copy link
Copy Markdown
Member

Closes the one CodeQL alert left open after the v2 tree swap (#1817).

The alert

#64 — medium — actions/missing-workflow-permissions on .github/workflows/main.yml:13:

Actions job or workflow does not limit the permissions of the GITHUB_TOKEN.

The other 10 alerts surfaced by the swap were all test fixtures and were dismissed as used in tests. This one is real infrastructure, so it wasn't dismissible under that reason.

Why it's worth more than "medium"

This is the workflow that publishes to npm under OIDC trusted publishing. An over-permissioned GITHUB_TOKEN in a workflow that mints publish credentials is worth tightening before 2.0.0 goes out (#1818), not after.

The change

A workflow-level default:

permissions:
  contents: read

The build job needs nothing more. The two publish jobs already declare their own blocks (id-token: write, packages: write, attestations: write) and are unaffected — job-level permissions override the workflow-level default outright rather than merging with it.

That override semantic is the one trap here, so the comment in the file records it: each publish job must keep listing every scope it needs, including contents: read. A future edit that trims one "because it's inherited from the top" would silently break publishing.

Verification

  • Additive only — 9 lines, no existing line modified
  • permissions parses as a top-level key alongside name / on / jobs
  • Both job-level permissions: blocks still present; both id-token: write occurrences intact

Provenance

Pre-existing on v2/mainmain had simply never scanned this workflow before the swap. Not introduced by #1830.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD

CodeQL alert #64 (`actions/missing-workflow-permissions`, medium) on
`.github/workflows/main.yml`: no `permissions` block, so every job inherits the
repository's default GITHUB_TOKEN scope, which is broader than anything here
needs.

It matters more than the severity suggests because this is the workflow that
publishes to npm under OIDC — an over-permissioned token in a job that mints
publish credentials is worth tightening before 2.0.0 ships (#1818).

Adds a workflow-level `permissions: contents: read`. The `publish` and
`publish-github-container-registry` jobs already declare their own blocks
(`id-token: write` and friends) and are unaffected: job-level permissions
override the workflow-level default outright rather than merging with it. The
comment records that, since it means each publish job must keep listing every
scope it needs — including `contents: read` — and a future edit that trims one
"because it's inherited" would break the publish.

Surfaced by the v2 tree swap (#1817): `main` had never scanned this workflow
before. Pre-existing on `v2/main`, not introduced by that merge.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Txmv2qqv3yeKgRzoqXytzD
@cliffhall cliffhall added the v2 Issues and PRs for v2 label Jul 28, 2026
@cliffhall
cliffhall merged commit 809b9fd into main Jul 28, 2026
6 checks passed
@cliffhall
cliffhall deleted the fix/1817-workflow-token-permissions branch July 28, 2026 03:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

v2 Issues and PRs for v2

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant