LearnNewsExamplesServices
Frontmatter
id13252
titleHarden GitHub write guard against future unguarded tools
stateClosed
labels
enhancementdeveloper-experienceaitestingarchitecturemodel-experience
assigneesneo-gpt
createdAtJun 14, 2026, 8:34 PM
updatedAtJun 15, 2026, 1:10 AM
githubUrlhttps://github.com/neomjs/neo/issues/13252
authorneo-gpt
commentsCount0
parentIssue13012
subIssues[]
subIssuesCompleted0
subIssuesTotal0
blockedBy[x] 13243 Fail closed on GitHub write identity drift
blocking[]
closedAtJun 15, 2026, 1:10 AM

Harden GitHub write guard against future unguarded tools

Closed v13.1.0/archive-v13-1-0-chunk-2 enhancementdeveloper-experienceaitestingarchitecturemodel-experience
neo-gpt
neo-gpt commented on Jun 14, 2026, 8:34 PM

Context

PR #13246 adds the immediate fail-closed GitHub Workflow write-boundary identity guard for the 2026-06-14 GH_TOKEN identity-drift incident. During review, Ada posted a non-blocking Approve+Follow-Up finding: the current guard is complete for the current write set, but its protection boundary depends on a hand-maintained allowlist of mutating tools.

Source review: https://github.com/neomjs/neo/pull/13246#pullrequestreview-4493363935

Live evidence gathered before filing:

  • #13246 introduces PUBLIC_GITHUB_WRITE_TOOLS, isPublicGitHubWriteTool, and guardGitHubWriteTools in ai/mcp/server/github-workflow/toolService.mjs.
  • The #13246 test suite explicitly checks the current listed write tools and current listed non-write tools.
  • That proves current coverage, but it does not prove future completeness when a new public GitHub mutation tool is added to serviceMapping / OpenAPI.
  • Live latest-open sweep: checked latest 30 open issues at 2026-06-14T18:33Z; adjacent #13243 and #13244 exist, but no equivalent future-write guard-completeness hardening ticket was found.
  • A2A in-flight sweep: checked latest 30 messages at 2026-06-14T18:33Z; no overlapping [lane-claim] / [lane-intent] for this follow-up was found.
  • Knowledge Base semantic sweep was attempted first and failed with Knowledge Base is not available: Failed to access collections; live GitHub, the #13246 diff/review, and local search are the authority for this filing.

Release classification: post-release (Approve+Follow-Up follow-up — non-blocking for #13246).

The Problem

A security boundary that protects only a hand-maintained write-tool set can fail open in the future: if a new GitHub Workflow MCP tool mutates public GitHub state and is added to serviceMapping without also being added to PUBLIC_GITHUB_WRITE_TOOLS, the identity guard will not wrap it. The failure would be silent until another identity-drift incident exercises the new tool.

This is not a blocker for #13246 because the current write surface is covered. It is a durable hardening follow-up because the next write-tool addition should either be guarded by construction or fail CI when the classification is incomplete.

The Architectural Reality

  • The GitHub Workflow MCP boundary is the public-write choke point for issue, PR, discussion, and relationship mutations.
  • #13246 guards the current mutation surface by wrapping entries whose operation id appears in PUBLIC_GITHUB_WRITE_TOOLS.
  • serviceMapping is the runtime dispatch map; openapi.yaml is the tool-description surface; tests currently assert the known read/write classification, not the completeness invariant for future additions.
  • The sibling #13244 healthcheck detects identity drift before writes, but it is a detection seam. This ticket is about preventing future write tools from bypassing the enforcement seam.

The Fix

Add a durable completeness invariant for GitHub Workflow public-write identity enforcement. Acceptable implementation shapes include:

  • derive the guarded write set from a canonical mutation source, so new mutating operations are guarded automatically;
  • invert the policy to fail closed by default and explicitly allow known read-only tools;
  • or add a guard-completeness test that compares the runtime dispatch surface against a canonical mutation classification and fails when any public GitHub mutation is unguarded.

The chosen implementation must make the next public GitHub write-tool addition either guarded automatically or rejected by focused tests before merge.

Contract Ledger Matrix

Target Surface Source of Authority Proposed Behavior Fallback Docs Evidence
ai/mcp/server/github-workflow/toolService.mjs write guard #13246 guard seam + current serviceMapping Future public GitHub write tools cannot bypass buildGitHubWriteIdentityGuard by missing an allowlist entry Fail CI or fail closed by default when classification is incomplete JSDoc / inline test intent Focused unit tests over runtime mapping / canonical classification
GitHub Workflow tool classification serviceMapping + openapi.yaml / chosen canonical mutation source Every operation id has a durable read/write classification relevant to identity enforcement Unknown tools must not silently behave as unguarded writes Test names and assertion messages Synthetic future-write falsifier or full mapping completeness assertion
Existing read tools Current read-only operation list Reads remain callable under identity drift unless the chosen fail-closed design intentionally checks all tools Any extra read-side check must be documented as intentional PR body + test evidence Regression test for representative read tools

Decision Record impact

Aligned with ADR 0020 / Agent Harness hardening direction. No ADR amendment required; this is a post-review hardening leaf under the Agent Harness / GitHub Workflow MCP boundary.

Acceptance Criteria

  • The implementation removes or neutralizes the future fail-open risk in which a newly added public GitHub write tool is present in serviceMapping but not protected by the identity guard.
  • A focused unit test fails against a synthetic or real unguarded-write addition before the fix, and passes after the fix.
  • Current public write tools remain guarded by buildGitHubWriteIdentityGuard or an equivalent shared enforcement path.
  • Current read-only tools either remain unguarded or are intentionally guarded under a documented fail-closed-by-default design; no accidental read-path regression is introduced.
  • The PR body cites #13246 as the prerequisite and states whether the implementation chose canonical derivation, fail-closed default, or completeness-test enforcement.

Out of Scope

  • Changing #13246's current identity assertion semantics.
  • Ada's separate structured error-code follow-up for assertExpectedIdentity reason parsing.
  • GitHub Workflow healthcheck detection behavior from #13244.
  • Non-GitHub MCP servers.

Avoided Traps / Gold Standards Rejected

  • Leave the review prose as the only record — rejected by the post-review follow-up surfacing rule; durable follow-ups need graph-visible tickets.
  • Block #13246 on this hardening — rejected because #13246 is complete for the current write surface and this is a future-change invariant.
  • Mandate one implementation strategy now — rejected because the best shape should be chosen against the post-#13246 merged code and current OpenAPI / dispatch topology.

Related

Parent: #13012 Blocked by: #13246 Related: #13243 Related: #13244

Origin Session ID: 4ed21ddf-b92f-45ce-8689-bb3ebb563dd9

Handoff Retrieval Hints: search for PUBLIC_GITHUB_WRITE_TOOLS, guardGitHubWriteTools, isPublicGitHubWriteTool, and #13246 review Finding A; query raw memories for github workflow identity guard completeness fail-open future write tools.