From 94f3733993820f9cf59c5b421846265218439346 Mon Sep 17 00:00:00 2001 From: Lars Vikberg Date: Wed, 23 Sep 2026 23:24:12 +0200 Subject: [PATCH] Move github-mcp-server to v1.12.2, which turns lockdown on MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## What `mcp-github` goes from v1.9.0 to v1.12.2. No configuration changes; the one comment that changes is the lockdown one, because what it described was not happening. ## Lockdown was never on On v1.9.0, http mode computed lockdown as `d.lockdownMode && ghcontext.IsLockdownMode(ctx)` — the server's `GITHUB_LOCKDOWN_MODE` AND a per-request `X-MCP-Lockdown` header. Nothing in dockade sends that header, so the `"1"` in `mcp-servers.yml` did nothing. v1.10.0 (github/github-mcp-server#3112) made it `||`, so the server setting is sufficient on its own. That makes this bump a behaviour change and not only a version: public-repo content from authors without push access is now filtered from results. It is the second of this server's flags found inert — read-only was the first, through v0.31.0 — and the comment now says so, next to the reminder that neither flag is the boundary. ## What else moved, and why none of it is a regression here Read from the release notes, the upstream source and the tool snapshots at both tags; the evidence is in `NOTES.md`. - New write tools. A tool with no rule is `ask`, so every one arrives held. In the catalogue's default toolsets that is `update_issue_comment`; with `GITHUB_MCP_TOOLSETS=all` also `create_repository_ruleset` and `custom_properties_write`, from a new Governance toolset. - `delete_repository` is in the snapshots but the running server does not list it. It could not succeed through dockade anyway: it confirms through a multi-round-trip elicitation read from `req.Params.InputResponses`, and the gateway sends `name` and `arguments` only. - No dispatcher in the default toolsets grew. Under `all`, `projects_write` gains three project-view methods including `delete_project_view` — a rule written for it on v1.9.0 now decides those too — and `repository_ruleset_read` is a new five-method dispatcher, all reads. - Per-call OAuth scope challenges (v1.11.0) act only on `gho_` tokens; the classic-PAT filter still skips itself when the scope lookup fails, so dummy-token enumeration is unchanged. - The server's new 5 MiB request cap is above the gateway's. - `arguments: null` is now rejected; the gateway already sends `{}`. - Symlink writes via `create_or_update_file` now need `allow_symlink_write: true`. Worth building on later: `merge_pull_request` gains `expectedHeadSha`, which makes GitHub refuse a merge whose head moved after it was reviewed. ## Tests - `make lint`, `make consistency`, `make test` pass. - On the host, with the new image running: `make mcp-tools SERVER=github` lists 25 tools, all read-only, with the dispatchers' methods unchanged, on the catalogue defaults; and 90 tools, 34 not read-only, with `GITHUB_MCP_TOOLSETS=all` and `GITHUB_MCP_READ_ONLY=0` — matching the snapshot diff except that `delete_repository` is withheld. `make check-boundary` passes (26 checks). - A real `get_file_contents` through the gateway returned the repository root — gateway, server, egress proxy and injected token end to end. Not exercised: lockdown filtering itself. Co-Authored-By: Claude --- NOTES.md | 51 +++++++++++++++++++++++++++++++++++++++++++++++++ mcp-servers.yml | 6 +++++- 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/NOTES.md b/NOTES.md index f661233..00a8c1b 100644 --- a/NOTES.md +++ b/NOTES.md @@ -431,6 +431,57 @@ reaches at all, by either route. 113,844 bytes and still 55%. The result also declares `ttlMs: 0` and `cacheScope: "public"` — the server's own answer to whether its list may be cached is no. +## `mcp-github` v1.9.0 → v1.12.2: lockdown was never on, and what else moved + +Read from the upstream source and tool snapshots (`pkg/github/__toolsnaps__/`) at both +tags, not measured against a running container. + +**`GITHUB_LOCKDOWN_MODE` was inert on v1.9.0.** In http mode the effective flag was +`d.lockdownMode && ghcontext.IsLockdownMode(ctx)` (`pkg/github/dependencies.go`) — the +server setting AND a per-request `X-MCP-Lockdown` header, which nothing in dockade sends. +v1.10.0 (github/github-mcp-server#3112) made it `||`, so the server setting is an upper +bound on its own. It is the same shape as the read-only flag through v0.31.0: set, +documented, and doing nothing. The consequence of the bump is that lockdown turns ON — +public-repo content from authors without push access is filtered from results. + +**Tool surface within `context,repos,issues,pull_requests`**, from the snapshots: + +- two new write tools in the snapshots: `update_issue_comment`, and + `delete_repository`. The latter completes only through a multi-round-trip + elicitation read from `req.Params.InputResponses`, which the gateway does not relay + (it sends `name` and `arguments`, nothing else), and needs the `delete_repo` scope — + and the running server does not list it at all (below); +- `merge_pull_request` gains optional `expectedHeadSha` (GitHub rejects the merge if the + head moved); `issue_write` gains `parent_*` for atomic sub-issue creation; + `create_or_update_file` gains `allow_symlink_write`, and symlink writes now need it; +- no dispatcher's `method` enum grew. `pull_request_read`, `issue_read`, + `pull_request_review_write` and `issue_write` keep the operation sets listed above. + +**With `GITHUB_MCP_TOOLSETS=all` and `GITHUB_MCP_READ_ONLY=0`** — measured with `make +mcp-tools SERVER=github` on v1.12.2: 90 tools, 34 not read-only. Against the snapshots: + +- `delete_repository` is NOT listed. The server withholds it here — the snapshot has + it, the running server does not offer it — so it is absent rather than merely + unable to complete. The three reaction removals are absent too: they are in the + granular toolsets, which `all` does not include; +- new write tools that ARE listed: `update_issue_comment`, and from a new Governance + toolset `create_repository_ruleset` and `custom_properties_write`, beside + `custom_properties_read` and `repository_ruleset_read` — the last a new + dispatcher, five read methods under one name; +- `projects_write` gains `create_project_view`, `update_project_view` and + `delete_project_view`, so a rule written for it on v1.9.0 now also decides deleting + a project view; `projects_get` and `projects_list` gain view reads; +- the two notification-subscription tools now declare `destructiveHint: true`. + +**Per-call OAuth scope challenges (v1.11.0) do not apply to a PAT.** The middleware acts +only on `gho_` OAuth tokens. The classic-PAT tool filter still skips itself when the +scope lookup fails, so the gateway's dummy `ghp_` enumeration is unaffected; a real +classic PAT is filtered under the rewritten visibility rules, a fine-grained one not at +all. + +**The server's new request-body cap is 5 MiB** (github/github-mcp-server#3111), above +the gateway's own, so the gateway's stays the one a caller meets. + ## What a sandbox session and a cold build actually cost Two sets of figures DESIGN.md used to carry inline, where they were both evidence for a diff --git a/mcp-servers.yml b/mcp-servers.yml index b12f5ed..c40e92c 100644 --- a/mcp-servers.yml +++ b/mcp-servers.yml @@ -67,7 +67,7 @@ services: - mcp-github # Pinned deliberately: this container holds a write-capable credential, so an # unreviewed `latest` would be an auto-updating supply chain into it. - image: ghcr.io/github/github-mcp-server:v1.9.0 + image: ghcr.io/github/github-mcp-server:v1.12.2 container_name: mcp-github hostname: mcp-github # `http` is the streamable-HTTP transport. stdio is the image's default and is @@ -107,6 +107,10 @@ services: # Limits what content from PUBLIC repos is surfaced, by checking whether the # author has push access. Directly aimed at the response-side risk: issue and # PR bodies are attacker-authored text that lands in the agent's context. + # In effect only from v1.10.0: before it, http mode also required a per-request + # `X-MCP-Lockdown` header (github/github-mcp-server#3112), which the gateway + # never sends — the second of this server's flags found inert (NOTES.md). Like + # read-only, a best-effort filter and not the boundary. GITHUB_LOCKDOWN_MODE: "1" # Real process env, not a shell export (same rule as the sandbox's proxy # vars). Go's net/http honours these; a Node-based server would not without