You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
#2274 scoped the static-token GITTENSORY_MCP_TOKENwrite/manage MCP tool paths (requireRepoManageAccess, requireRepoApprovalQueueAccess) to an operator-configured repo allowlist. The read-access guards were left unscoped:
canAccessRepo/requireRepoAccess, requireContributorAccess, requireOperatorAccess, and requireWatchableRepo (src/mcp/server.ts ~line 2033 and surrounding) all unconditionally trust the shared static mcp identity — canAccessRepo returns true immediately whenever this.identity.kind !== "session", so the maintainer/owner/operator permission check (canLoginAccessRepo) is never invoked for a static-token caller.
GITTENSORY_MCP_TOKEN is an ordinary, end-user-obtainable CLI credential (see env.d.ts ~lines 141-146 and the #2274 commit message itself, which states this explicitly). As things stand, any holder of that token can:
call gittensory_get_repo_context / gittensory_get_issue_quality / gittensory_preflight_pr / gittensory_get_outcome_calibration / gittensory_validate_linked_issue / gittensory_get_maintainer_noise / gittensory_get_label_audit against a private repo they have no GitHub collaborator access to,
call gittensory_get_decision_pack / gittensory_get_contributor_profile / gittensory_monitor_open_prs for an arbitrary other login to pull that contributor's private decision pack (requireContributorAccess, ~lines 1769-1773, same session-only guard),
call gittensory_get_fleet_analytics (requireOperatorAccess, ~lines 2069-2074) to pull cross-instance operator-only fleet calibration data — the code comment there literally says "private-token / static identities are trusted," which is the opposite of the posture fix(mcp): scope the static MCP token to an operator-configured repo allowlist #2274 just established for the write path.
Fix
Extend the same allowlist-scoping pattern #2274 applied to requireRepoManageAccess/requireRepoApprovalQueueAccess to canAccessRepo/requireRepoAccess, requireContributorAccess, requireOperatorAccess, and requireWatchableRepo for the static mcp identity: deny by default, require an explicit operator opt-in — matching the rationale already documented at server.ts ~lines 1780-1784 and 1811.
Regression tests
A static-token call to each of the read-access tools listed above against a repo NOT on the allowlist is denied.
A static-token call against an allowlisted repo still succeeds (no regression for the intended broker/CLI use case).
Operator/fleet-analytics tools reject the static identity unless explicitly opted in, matching the write-path posture.
Parent: #1936
Problem
#2274 scoped the static-token
GITTENSORY_MCP_TOKENwrite/manage MCP tool paths (requireRepoManageAccess,requireRepoApprovalQueueAccess) to an operator-configured repo allowlist. The read-access guards were left unscoped:canAccessRepo/requireRepoAccess,requireContributorAccess,requireOperatorAccess, andrequireWatchableRepo(src/mcp/server.ts~line 2033 and surrounding) all unconditionally trust the shared staticmcpidentity —canAccessReporeturnstrueimmediately wheneverthis.identity.kind !== "session", so the maintainer/owner/operator permission check (canLoginAccessRepo) is never invoked for a static-token caller.GITTENSORY_MCP_TOKENis an ordinary, end-user-obtainable CLI credential (seeenv.d.ts~lines 141-146 and the #2274 commit message itself, which states this explicitly). As things stand, any holder of that token can:gittensory_get_repo_context/gittensory_get_issue_quality/gittensory_preflight_pr/gittensory_get_outcome_calibration/gittensory_validate_linked_issue/gittensory_get_maintainer_noise/gittensory_get_label_auditagainst a private repo they have no GitHub collaborator access to,gittensory_get_decision_pack/gittensory_get_contributor_profile/gittensory_monitor_open_prsfor an arbitrary other login to pull that contributor's private decision pack (requireContributorAccess, ~lines 1769-1773, same session-only guard),gittensory_get_fleet_analytics(requireOperatorAccess, ~lines 2069-2074) to pull cross-instance operator-only fleet calibration data — the code comment there literally says "private-token / static identities are trusted," which is the opposite of the posture fix(mcp): scope the static MCP token to an operator-configured repo allowlist #2274 just established for the write path.Fix
Extend the same allowlist-scoping pattern #2274 applied to
requireRepoManageAccess/requireRepoApprovalQueueAccesstocanAccessRepo/requireRepoAccess,requireContributorAccess,requireOperatorAccess, andrequireWatchableRepofor the staticmcpidentity: deny by default, require an explicit operator opt-in — matching the rationale already documented atserver.ts~lines 1780-1784 and 1811.Regression tests