From 6d4a47884776cc0dabd183aee7770896932a4736 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Thu, 22 Oct 2026 09:27:26 +0100 Subject: [PATCH 1/2] ci: give the registry job least privilege and pin its action to a commit The workflow-level permissions grant write on contents, issues and pull requests to every job. The registry job needs a read checkout and the OIDC token the registry login uses, and it runs an action whose tag can move, so it now declares exactly those permissions and pins the action to the commit of its release, as GitHub's secure use guidance recommends. --- .github/workflows/ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bb8548ad..e769a5ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -220,6 +220,10 @@ jobs: if: ${{ !cancelled() && needs.release.result != 'failure' && ((github.ref == 'refs/heads/main' && github.event_name == 'push') || github.event_name == 'workflow_dispatch') }} needs: [release] runs-on: ubuntu-latest + # The workflow-level permissions are broad enough for the release job (contents, issues and pull requests, all write). This job runs a third-party-shaped action with the OIDC token that publishes under this repository's registry namespace, so it gets only what the action's own README asks for: a read checkout and the OIDC token. A moved tag on that action then cannot write to this repository. + permissions: + contents: read + id-token: write steps: # A push to main publishes what the release job just committed, which is main's new tip and not the commit this run started from. The publisher is the pinned `ExaDev/mcp-registry-publish` action, never code from a release tag, so a backfill of an old version runs today's retry handling; a dispatch naming a `registry_ref` takes only that tag's server.json from it. - uses: actions/checkout@v7 @@ -232,5 +236,6 @@ jobs: run: | git fetch --depth=1 origin "refs/tags/${REGISTRY_REF}" git show FETCH_HEAD:server.json > server.json - - uses: ExaDev/mcp-registry-publish@v1 + # Pinned to the commit of the release, not the moving major tag: GitHub's secure use guidance is a full-length SHA, since a tag can be moved, and this step holds the registry publishing identity. Dependabot's github-actions updates keep the pin current. + - uses: ExaDev/mcp-registry-publish@4de3ca0cf0f9cf19184c4c65f97d22e3caf18fb3 # v1.0.1 From 911bca92911a7266f12443b2cd51749379255d37 Mon Sep 17 00:00:00 2001 From: Joseph Mearman Date: Thu, 22 Oct 2026 09:46:21 +0100 Subject: [PATCH 2/2] ci: pin the registry action to the release that logs each retry's cause --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e769a5ee..c032e562 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -237,5 +237,5 @@ jobs: git fetch --depth=1 origin "refs/tags/${REGISTRY_REF}" git show FETCH_HEAD:server.json > server.json # Pinned to the commit of the release, not the moving major tag: GitHub's secure use guidance is a full-length SHA, since a tag can be moved, and this step holds the registry publishing identity. Dependabot's github-actions updates keep the pin current. - - uses: ExaDev/mcp-registry-publish@4de3ca0cf0f9cf19184c4c65f97d22e3caf18fb3 # v1.0.1 + - uses: ExaDev/mcp-registry-publish@b8148f254d6788ac7fd817a0bd8d8f0abe4784d5 # v1.0.3