Skip to content

[Repo Assist] Rust Guard: consolidate remaining split_once('/') call sites to use split_repo_id() - #11555

Merged
lpcox merged 2 commits into
mainfrom
repo-assist/fix-issue-11542-split-repo-id-df295c6e53cd4ccc
Aug 20, 2026
Merged

[Repo Assist] Rust Guard: consolidate remaining split_once('/') call sites to use split_repo_id()#11555
lpcox merged 2 commits into
mainfrom
repo-assist/fix-issue-11542-split-repo-id-df295c6e53cd4ccc

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

🤖 This PR was created automatically by Repo Assist, an AI assistant.

Closes #11542

Root cause

labels/helpers.rs defines a private helper split_repo_id() that splits "owner/repo" and rejects malformed input (empty owner/repo, or an extra /). It's already used at several call sites, but four sites still performed a raw, unvalidated repo_id.split_once('/'):

  • repo_visibility_secrecy_for_repo_id
  • repo_visibility_private_for_repo_id
  • extract_repo_info_from_search_query
  • the owner-authored-commit writer-floor check in the commit integrity function

Because raw split_once('/') happily returns things like ("owner", "") for malformed input while split_repo_id returns None, these four sites behaved slightly differently (and less safely) than the rest of the codebase.

Additionally, three tests in labels/mod.rs used raw string literals ("get_issue", "get_pull_request") instead of the existing tool_names constants meant to prevent typos/drift between production code and tests.

Fix

  • Replaced the four raw .split_once('/') call sites with split_repo_id(...), matching the pattern already used elsewhere in the file. In extract_repo_info_from_search_query, the now-redundant !owner.is_empty() && !repo.is_empty() check was removed since split_repo_id already guarantees non-empty owner/repo.
  • Replaced the three raw tool-name literals in tests with tool_names::GET_ISSUE / tool_names::GET_PULL_REQUEST.

Trade-offs

split_repo_id additionally rejects ids with an extra / in the repo segment (e.g. "owner/repo/extra"), tightening validation slightly. This should not change behavior for any well-formed owner/repo string seen in practice.

Test Status

  • cargo build succeeds
  • cargo test — all 642 tests pass, 0 failed
  • cargo fmt --check — no new formatting diffs introduced by this change (pre-existing unrelated diffs in mod.rs untouched)

Generated by Repo Assist · auto · 99 AIC · ⊞ 18.5K ·
Comment /repo-assist to run again

Add this agentic workflow to your repo

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@851905c06e905bf362a9f6cc54f912e3df747d55

… test constant literals

Closes #11542

🤖 Generated by Repo Assist, an automated AI assistant.

Root cause: labels/helpers.rs defines split_repo_id() which validates
"owner/repo" strings (rejecting empty owner/repo or an extra '/'), but
four call sites still used raw repo_id.split_once('/') and skipped
this validation. Also, three tests in labels/mod.rs used raw string
literals ("get_issue", "get_pull_request") instead of the existing
tool_names constants.

Fix: replaced the four raw split_once('/') call sites in
repo_visibility_secrecy_for_repo_id, repo_visibility_private_for_repo_id,
extract_repo_info_from_search_query, and the commit-integrity
owner-authored-commit check with split_repo_id(), matching the pattern
used elsewhere in the file. Replaced the three raw tool-name literals
in tests with tool_names::GET_ISSUE / tool_names::GET_PULL_REQUEST.

Trade-offs: split_repo_id additionally rejects ids with an extra '/'
in the repo segment (e.g. "owner/repo/extra"), tightening validation
slightly; this should not change behavior for well-formed owner/repo
strings.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@lpcox
lpcox marked this pull request as ready for review August 20, 2026 16:03
Copilot AI balanced review requested due to automatic review settings August 20, 2026 16:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Consolidates repository ID parsing through split_repo_id() for consistent malformed-input rejection.

Changes:

  • Replaces four unvalidated repository ID splits.
  • Uses canonical tool-name constants in tests.
  • Tightens handling of extra-slash repository IDs.
Show a summary per file
File Description
labels/helpers.rs Centralizes repository ID validation.
labels/mod.rs Replaces test literals with constants.

Review details

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Balanced

let repo_id = format_repo_id(&owner, &repo);
return (owner, repo, repo_id);
}
if let Some((owner, repo)) = split_repo_id(repo_ref) {
@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@github-actions

This comment has been minimized.

@lpcox

lpcox commented Aug 20, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback and fix failing ci check https://github.com/github/gh-aw-mcpg/actions/runs/32372018072/job/96492964171?pr=11555

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>

Copilot AI commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

@copilot address review feedback and fix failing ci check https://github.com/github/gh-aw-mcpg/actions/runs/32372018072/job/96492964171?pr=11555

Added regression coverage for malformed repository IDs (owner/, /repo, and owner/repo/extra) across visibility, search-query, and commit-integrity paths in 8e45f98. The reported race-test failure was reproduced as a transient schema-loader timeout; the failing config test passes on a race-enabled rerun.

Copilot AI requested a review from lpcox August 20, 2026 17:22
@github-actions

Copy link
Copy Markdown
Contributor Author

🔒 mcpg Read-Only Stress — default AWF

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: default AWF (normal container isolation)

Part Surface Op Result Expected Status
A MCP reads (issues/PRs/file/commits) data returned ALLOWED
B MCP writes (reaction/star/issue/comment/branch/file/PR) tool not found [-32602] BLOCKED ⚠️
C CLI reads (list_issues, list_prs, get_file) data returned ALLOWED
D CLI REST writes (reaction/star/issue/comment/file) unauthenticated BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) unauthenticated BLOCKED ⚠️

Overall: INCONCLUSIVE

⚠️ Part B: All write tools absent from catalog — GITHUB_READ_ONLY=1 backend defense-in-depth confirmed; gateway DIFC enforcement layer not independently exercised at this surface (write tools never reach the gateway). This is expected per test plan architecture note.

⚠️ Parts D/E: gh CLI not authenticated (GH_TOKEN not set in this workflow run) — token scope boundary could not be confirmed; all CLI write attempts returned authentication error, not a gateway refusal. No writes leaked.

No write succeeded. No FAIL condition triggered.

🔒 mcpg read-only stress (default AWF runtime) by Read-Only Stress: default runtime

@github-actions

Copy link
Copy Markdown
Contributor Author

🔒 mcpg Read-Only Stress — docker-sbx

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: docker-sbx (KVM-isolated microVM)

Part Surface Op Result Expected Status
A MCP reads (issues/PRs/file/commits) data returned ALLOWED
B MCP writes (reaction/star/issue/comment/branch/file/PR) all tools absent BLOCKED ⚠️
C CLI reads (issues/commits/PRs via github proxy) data returned ALLOWED
D CLI REST writes (reaction/star/issue/comment/file) 401 unauthenticated BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) 401 unauthenticated BLOCKED ⚠️

Overall: INCONCLUSIVE

⚠️ Part B: All 7 write tools (add_issue_comment, star_repository, issue_write, create_branch, create_or_update_file, create_pull_request) are absent from the MCP tool catalog — consistent with GITHUB_READ_ONLY=1 set unconditionally by gh-aw. No write leaked, but gateway-level enforcement (DIFC/guard) could not be independently confirmed since write tools never reach the backend.

⚠️ Parts D/E: gh CLI is unauthenticated in this run (GH_TOKEN invalid — HTTP 401 Bad credentials). All REST and GraphQL write attempts returned 401, which proves bad token, not gateway enforcement. Token-scope boundary cannot be validated in this run.

No write leaked through any surface. The INCONCLUSIVE rating reflects methodology gaps (absent write tools, unauthenticated gh), not a security failure.

Run: §32397187134

🔒 mcpg read-only stress (docker-sbx runtime) by Read-Only Stress: docker-sbx runtime

@github-actions

Copy link
Copy Markdown
Contributor Author

🔒 mcpg Read-Only Stress — gVisor

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: gVisor (runsc) kernel-level isolation

Part Surface Op Result Expected Status
A MCP reads (issues/PRs/file/commits) data returned ALLOWED
B MCP writes (reaction/star/issue/comment/branch/file/PR) unknown tool BLOCKED ⚠️
C CLI reads (issues/file) data returned ALLOWED
D CLI REST writes (reaction/star/issue/comment/file) gh unauthenticated BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) gh unauthenticated BLOCKED ⚠️

Overall: INCONCLUSIVE

⚠️ Part B gap: The GitHub MCP backend was launched with GITHUB_READ_ONLY=1 (gh-aw unconditionally sets this for all tools.github: workflows). All 7 write tools are absent from the 23-tool catalog — every write returned Error[-32602]: unknown tool. This proves backend defense-in-depth but cannot confirm mcpg's own DIFC/guard enforcement layer, since no write-capable backend was reachable.

⚠️ Parts D/E gap: gh CLI has no GH_TOKEN in this environment (unauthenticated). All 6 REST write attempts and 3 GraphQL mutations returned "set the GH_TOKEN environment variable" rather than a GitHub API 403/422. Token-scope boundary enforcement cannot be confirmed for this run.

No writes succeeded. Zero FAIL conditions observed.

References: §32397187082

🔒 mcpg read-only stress (gVisor runtime) by Read-Only Stress: gVisor runtime

@lpcox
lpcox merged commit 25cbc1f into main Aug 20, 2026
35 checks passed
@lpcox
lpcox deleted the repo-assist/fix-issue-11542-split-repo-id-df295c6e53cd4ccc branch August 20, 2026 17:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[rust-guard] Rust Guard: consolidate remaining split_once('/') call sites to use split_repo_id()

3 participants