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
cliffhall added a commit that referenced this pull request Aug 2, 2026
…#1904)

main's copy of .github/workflows/main.yml carried three release fixes
v2/main never took -- #1831 (least-privilege default GITHUB_TOKEN
scope), #1834 (derive the npm dist-tag from the version) and #1836
(publish via npm OIDC trusted publishing).

Diffing the file both directions shows v2/main has NOTHING main lacks:
its only unique content is the superseded publish step,

    run: npm publish --access public --provenance
    env:
      NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

which is exactly what #1836 replaced. Every other line already matched.
So this is a verbatim copy of main's file rather than a hunk-by-hunk
forward-port -- fewer ways to get it wrong, and it leaves the two
branches byte-identical (`git diff origin/main -- .github/workflows`
is now empty).

Not a back-merge: only this one file is taken, so none of main's
pre-swap v1 lineage enters v2/main's ancestry (see #1868).


Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
pull Bot pushed a commit to Bang2985/inspector that referenced this pull request Aug 5, 2026
Resolves the eight conflicts from the first v2/main -> main milestone
merge on a branch cut from main, so v2/main's ancestry stays clean --
resolving them on the PR head would have back-merged main into v2/main,
which is exactly what modelcontextprotocol#1868 was closed to avoid.

All eight took v2/main's side, each verifiably the newer content:

- README.md          stale Mcp-Param-* callout; v2/main's is corrected
                     by modelcontextprotocol#1847 (the Inspector builds the headers itself)
- SECURITY.md        add/add (modelcontextprotocol#1843 on main, modelcontextprotocol#1867 on v2/main); differ
                     by one line, the CONTRIBUTORS.md -> CONTRIBUTING.md
                     rename from modelcontextprotocol#1884
- clients/web/package.json   vitest ^4.1.0 -> ^4.1.10, the modelcontextprotocol#1899 fix
- the five package-lock.json files, then regenerated from a clean
  install rather than hand-merged

main's release-workflow commits (modelcontextprotocol#1831 least-privilege token, modelcontextprotocol#1834
dist-tag derivation, modelcontextprotocol#1836 OIDC trusted publishing) auto-merged and are
preserved -- .github/workflows/main.yml is the only file where the
merged tree differs from v2/main.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YAt8rqxysNbhYWLhoRm3fU
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