Skip to content

Extract shared enclave/delegated request parse-and-route helper - #13694

Merged
lpcox merged 7 commits into
mainfrom
copilot/duplicate-code-fix-enclave-delegated
Sep 23, 2026
Merged

lpcox merged 7 commits into
mainfrom
copilot/duplicate-code-fix-enclave-delegated

Conversation

Copilot AI commented Sep 23, 2026 •

Copy link
Copy Markdown
Contributor

handleEnclaveRequest (internal/proxy/enclave.go) and handleDelegatedRequest (internal/proxy/delegation.go) each re-implemented the same admission skeleton — path extraction, GET/body validation, query parse, route match, tool/args resolution, fullPath reconstruction, handleWithDIFC dispatch — differing only in the authorization mechanism. Since both are security enforcement points, the copies could silently drift on validation order or denial conditions.

Changes

  • New internal/proxy/enclave_request.go: planEnclaveRequest(r) performs all shared request-shape work and returns an enclaveRequestPlan carrying path, fullPath, route, toolName, args, and a denial stage (path / requestShape / route / tool). The staged denial lets each handler keep its own log message while sharing one code path; every stage still yields the same 403 to clients.
  • routeAllowedBy(claims): nil-safe operation-policy check so plan.route is only dereferenced after a successful match.
  • Both handlers now consume the plan. Authorization stays caller-specific and is documented inline as the intentional difference: the enclave handler verifies capability claims and enforces the cross-repo public-visibility rule; the delegation handler authorizes against the delegated-identity store. Denial ordering in the enclave handler is unchanged (path → capability verification → request shape → operation policy → tool resolution → cross-repo visibility).
  • Tests (enclave_request_test.go): table-driven coverage for accepted routes, host-prefix stripping, invalid path, non-GET and GET-with-body, unmatched route, and tool resolution.
plan := planEnclaveRequest(r)
if !plan.ok() {
    // handler-specific logging per plan.denial
    writeEnclaveDenied(w)
    return
}
// handler-specific authorization ...
h.handleWithDIFC(w, r.WithContext(ctx), plan.fullPath, plan.toolName, plan.args, nil)

Copilot AI and others added 5 commits September 23, 2026 12:38
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
…l branch

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix duplicate code pattern in request handling Extract shared enclave/delegated request parse-and-route helper Sep 23, 2026
Copilot AI requested a review from lpcox September 23, 2026 12:50
@lpcox
lpcox marked this pull request as ready for review September 23, 2026 13:43
Copilot AI balanced review requested due to automatic review settings September 23, 2026 13:43

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.

Copilot review overview

🟡 Changes recommended

Enclave route planning now runs before capability verification, changing the documented security-check order and causing pre-authentication route logging.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity

Open (1)
What changed in this PR

Extracts shared enclave/delegation request parsing and routing logic to reduce security-critical duplication.

Changes:

  • Adds staged request planning and route/tool resolution.
  • Updates enclave and delegated handlers to consume shared plans.
  • Adds request-planning tests.
File Description
internal/​proxy/​enclave.go Uses shared request plans.
internal/​proxy/​enclave_request.go Implements shared planning logic.
internal/​proxy/​enclave_request_test.go Tests planning behavior.
internal/​proxy/​delegation.go Uses shared plans for delegated requests.

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

Comment thread internal/proxy/enclave.go Outdated
func (h *proxyHandler) handleEnclaveRequest(w http.ResponseWriter, r *http.Request) {
path, ok := enclavePath(r.URL.Path, r.URL.RawPath)
if !ok {
plan := planEnclaveRequest(r)
@github-actions

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — default

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 data returned (issues, PRs, README.md, commits) ALLOWED ✅
B MCP writes (reaction/star/issue/comment/branch/file/PR) all 7 write tools absent from catalog — only 23 read-only tools exposed BLOCKED ⚠️
C CLI reads data returned via github CLI proxy ALLOWED ✅
D CLI REST writes (reaction/star/issue/comment) not attempted — gh has no GH_TOKEN in this env BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) not attempted — same auth gap BLOCKED ⚠️

Overall: INCONCLUSIVE

No write leaked on any surface. Part A/C reads confirmed live data (README.md, list_issues, list_pull_requests, list_commits). However:

  • Part B: the github CLI proxy tool catalog contains only 23 read-only tools (get_file_contents, list_issues, search_code, etc.) — none of the targeted write tools (add_issue_comment, star_repository, issue_write, create_branch, create_or_update_file, create_pull_request) are present at all. This confirms backend/toolset config (GITHUB_READ_ONLY=1) but does not independently exercise the gateway's own DIFC/guard write-blocking layer, per the test's own methodology note.
  • Parts D/E: gh reported no GH_TOKEN configured in this environment (gh: To use GitHub CLI in a GitHub Actions workflow, set the GH_TOKEN environment variable), so no write attempts were possible — cannot validate the token-scope boundary this run.

No artifacts were created; no reactions, stars, issues, comments, branches, or files were added.

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

@github-actions

Copy link
Copy Markdown
Contributor

🔒 mcpg Read-Only Stress — gvisor

Surface coverage: MCP tool calls + proxied CLI (REST) + GraphQL mutations
Isolation runtime: gvisor

Part Surface Op Result Expected Status
A MCP reads (list_issues, list_pull_requests, get_file_contents, list_commits) data returned ALLOWED ✅
B MCP writes (add_issue_comment, star_repository, issue_write, create_branch, create_or_update_file, create_pull_request) all 6 absent from catalog ("Unknown command") BLOCKED ⚠️
C CLI reads (same 4 calls via github CLI proxy) data returned ALLOWED ✅
D CLI REST writes (reaction/star/issue/comment) not attempted — gh unauthenticated BLOCKED ⚠️
E CLI GraphQL mutations (addReaction/addStar/createIssue) not attempted — gh unauthenticated BLOCKED ⚠️

Overall: INCONCLUSIVE

Notes:

  • Part A/C reads all succeeded normally via the gateway-backed github CLI proxy (23-tool read-only catalog).
  • Part B: none of the 6 targeted write tools exist in the exposed catalog (backend launched with GITHUB_READ_ONLY=1 per gh-aw's tools.github: wrapper), so this confirms backend/toolset config, not mcpg's own gateway-level DIFC block. No write attempted or leaked.
  • Part D/E: gh auth status reported unauthenticated (You are not logged into any GitHub hosts) — the REST/GraphQL write probes could not be executed, so the token-scope boundary was not independently exercised this run. No writes attempted.
  • No reaction/star/issue/comment/branch/file/PR was created in any part.

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

@lpcox

lpcox commented Sep 23, 2026

Copy link
Copy Markdown
Collaborator

@copilot address review feedback

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

Copilot AI commented Sep 23, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address review feedback

Addressed in 8ed2c51: enclave handling now performs only path extraction before capability verification and defers query parsing, route matching, and tool resolution until afterward. Targeted tests and make agent-finished pass; Code Review and CodeQL report no findings.

@lpcox
lpcox merged commit 4f75f78 into main Sep 23, 2026
35 of 38 checks passed
@lpcox
lpcox deleted the copilot/duplicate-code-fix-enclave-delegated branch September 23, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[duplicate-code] Duplicate Code Pattern: Enclave and Delegated Request Handling Skeleton

3 participants