Skip to content

Disable forcePublicRepos for enclave-only GitHub MCP backends - #60016

Merged
lpcox merged 5 commits into
mainfrom
copilot/fix-static-github-agent-enclave
Sep 10, 2026
Merged

Disable forcePublicRepos for enclave-only GitHub MCP backends#60016
lpcox merged 5 commits into
mainfrom
copilot/fix-static-github-agent-enclave

Conversation

Copilot AI commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

A static GitHub agent enclave declared in a public repository reads nothing: the gateway's forcePublicRepos safety net rewrites the enclave's allow-only guard to repos: "public" at startup, discarding the configured allowed-repos. The enclave still starts, still debits the information budget, and still returns a schema-valid value — the failure is entirely silent, and the answer is ungrounded.

The compiler already emits a correct per-server and per-agent policy for the enclave identity; it just never told the gateway not to clobber it.

Changes

  • pkg/workflow/mcp_gateway_config.gobuildMCPGatewayConfig emits "forcePublicRepos": false when githubBackendIsStaticEnclaveDelegationOnly(workflowData) holds (tools.github: false + enclaves[].agent.tools.github). Only applied when the flag was not already derived from tools.github.private-to-public-flows, so explicit author configuration wins.
  • pkg/workflow/enclaves.gostaticEnclaveGitHubScopeOverrideWarning, emitted from enclave validation, covers the case the fix cannot: when the primary agent also enables tools.github, the override must stay on to protect the primary read path, so the enclave reads nothing. The warning names the discarded config path rather than failing silently.
  • Docs / changesetexperimental/enclaves.md and gateway spec §4.1.3.8 record the enclave exemption; changeset added.
  • Tests — gateway-config cases for enclave-only / primary-GitHub / no-enclave, a "forcePublicRepos": false lock-file assertion in the existing enclave-only compile test, and a warning test.

Why this is safe in the enclave-only case

forcePublicRepos: false is gateway-global, so it is only applied when the GitHub MCP server exists solely for the enclave identity:

  • the primary agent has no GitHub read path at all (tools.github: false);
  • disclosure remains bounded by the enclave's sensitivity ledger, max-output-bytes, and max-invocations;
  • forcePublicRepos: false only removes mcpg's default sink-visibility="public", and every write-sink policy the compiler emits on this path already carries an explicit sink-visibility (${GH_AW_SINK_VISIBILITY}), so safe-outputs enforcement is unchanged.
tools:
  github: false          # no primary GitHub read path
enclaves:
  - agent:
      tools:
        github:
          allowed: [list_issues, issue_read]
          allowed-repos: [octo-org/private-service]
          min-integrity: none
    repos:
      - repo: octo-org/private-service
        sensitivity: confidential

now compiles to a gateway config containing "forcePublicRepos": false, so the enclave's allow-only scope survives startup.

Not addressed here

Issue items 2–5 (fail-closed logging in overrideToPublicScope, enclave erroring on an empty tool inventory, ledger debits for read-free invocations, provenance derived from actual tool activity) and the agent-entrypoint.py stdout-artifact finding live in github/gh-aw-mcpg and github/gh-aw-firewall.

Copilot AI and others added 2 commits September 10, 2026 16:51
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
@github-actions

Copy link
Copy Markdown
Contributor

✅ This PR is from a trusted core team contributor using the Copilot coding agent. Per the project's CONTRIBUTING.md, internal agentic development is the standard workflow. The change looks ready for team review.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

Generated by ✅ Contribution Check · copilot · auto · 51.7 AIC · ⌖ 7.99 AIC · ⊞ 9.4K ·

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix static GitHub agent enclave reading errors Disable forcePublicRepos for enclave-only GitHub MCP backends Sep 10, 2026
Copilot AI requested a review from lpcox September 10, 2026 17:03
@lpcox
lpcox marked this pull request as ready for review September 10, 2026 17:26
Copilot AI balanced review requested due to automatic review settings September 10, 2026 17:26
@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Ponytail Reviewer completed successfully!

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • ab.chatgpt.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"

See Network Configuration for more information.

Generated by Ponytail Reviewer for #60016

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Design Decision Gate 🏗️ completed the design decision gate check. See the comment below for the result and any generated ADR draft.

No ADR enforcement needed: PR does not have the 'implementation' label and has ≤100 new lines of code in business logic directories.

🏗️ ADR gate enforced by Design Decision Gate 🏗️

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Test Quality Sentinel completed test quality analysis.

Test Quality Sentinel skipped because pre-fetch PR data was unavailable: unable to fetch test file diff

🧪 Test quality analysis by Test Quality Sentinel

@github-actions

github-actions Bot commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

PR Code Quality Reviewer completed the code quality review.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer

@github-actions github-actions Bot 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.

Nice targeted fix overall; only trim opportunities are comment verbosity in code paths that can be documented once in specs/docs.

net: -20 lines possible.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • ab.chatgpt.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "ab.chatgpt.com"

See Network Configuration for more information.

Generated by ✂️ Ponytail Reviewer for #60016 · codex · gpt53codex · 3.18 AIC · ⌖ 4.03 AIC · ⊞ 12.8K
Comment /ponytail to run again

Comment thread pkg/workflow/enclaves.go
// whole gateway, so it must stay enabled to protect the primary agent's read path. In a
// public repository that override rewrites the enclave's allow-only scope to repos="public",
// which silently discards enclaves[].agent.tools.github.allowed-repos and leaves the enclave
// unable to read the declared private repositories.

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.

L363: shrink: 7-line explanatory warning prose in code comments. Move rationale to docs and keep a 1-line function comment plus concise warning string.

}
}

// A static GitHub agent enclave is the mechanism that makes private-to-public

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.

L221: yagni: long policy narrative embedded in runtime builder comment. Keep intent in docs/spec and reduce to a short guard comment next to the condition.

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.

🟡 Changes recommended

The warning path misreports explicit opt-outs and bypasses compiler warning accounting.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

Disables the gateway’s public-repository override for enclave-only GitHub MCP backends while warning about shared primary-agent access.

Changes:

  • Adds enclave-aware forcePublicRepos configuration.
  • Adds validation warnings and regression tests.
  • Updates documentation and release notes.
File summaries
File Description
pkg/workflow/mcp_gateway_config.go Disables the override for enclave-only backends.
pkg/workflow/enclaves.go Adds the shared-backend warning.
pkg/workflow/enclave_github_proxy_test.go Tests configuration and warnings.
docs/src/content/docs/reference/mcp-gateway.md Documents gateway behavior.
docs/src/content/docs/experimental/enclaves.md Documents enclave configuration.
.changeset/enclave-force-public-repos.md Records the patch change.
Review details

Suppressed comments (1)

pkg/workflow/enclaves.go:365

  • When tools.github.private-to-public-flows: allow is set, buildMCPGatewayConfig already disables forcePublicRepos, but this still emits a warning claiming the override remains enabled and the enclave reads nothing. Suppress the warning for that explicit opt-out and cover this combination in the test.
	if !enclaveGitHubIssuesEnabled(workflowData) || !primaryGitHubMCPEnabled(workflowData) {
  • Files reviewed: 6/6 changed files
  • Comments generated: 3
  • Review effort level: Balanced

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

Comment thread pkg/workflow/enclaves.go Outdated
Comment on lines +351 to +352
if warning := staticEnclaveGitHubScopeOverrideWarning(workflowData); warning != "" {
fmt.Fprintln(os.Stderr, console.FormatWarningMessageStderr(warning))

Set `tools.github: false` so the GitHub MCP server is rendered for the enclave identity only. When primary-agent GitHub access is disabled, the compiler emits `"forcePublicRepos": false` in the gateway config: the gateway's runtime public-repos override would otherwise rewrite the enclave's allow-only scope to `repos: "public"` in a public repository, silently discarding `allowed-repos` and leaving the enclave with nothing to read. Disclosure stays bounded by the enclave's sensitivity ledger, `max-output-bytes`, and `max-invocations`, and safe outputs keep their explicit `sink-visibility` enforcement.

If the primary agent also enables `tools.github`, the override must stay on to protect the primary read path, and the compiler warns that the enclave cannot read the declared private repositories in a public repository.
- API errors during visibility detection result in a non-fatal warning; the gateway/proxy falls back to the compiled policy.

**Opt-out**: Workflow authors who intentionally allow private→public data flows set `private-to-public-flows: allow` in frontmatter (Section 10.9). The compiler translates this to `gateway.forcePublicRepos: false` in the generated gateway JSON stdin config. For proxy mode, launchers should pass `--force-public-repos=false` when they need equivalent opt-out behavior.
**Opt-out**: Workflow authors who intentionally allow private→public data flows set `private-to-public-flows: allow` in frontmatter (Section 10.9). The compiler translates this to `gateway.forcePublicRepos: false` in the generated gateway JSON stdin config. The compiler also emits `gateway.forcePublicRepos: false` when the GitHub MCP server is rendered solely to serve a static agent enclave identity (`tools.github: false` plus `enclaves[].agent.tools.github`), because the override would otherwise discard the enclave's configured `allowed-repos`. For proxy mode, launchers should pass `--force-public-repos=false` when they need equivalent opt-out behavior.
@github-actions

Copy link
Copy Markdown
Contributor

Comment Memory

reviewed_at: 2026-09-10T17:30:50.548+00:00
review_event: REQUEST_CHANGES
top_themes:
  - false-positive compiler warning for explicit private-to-public opt-out
  - false-positive compiler warning for private repositories
files_reviewed:
  - .changeset/enclave-force-public-repos.md
  - docs/src/content/docs/experimental/enclaves.md
  - docs/src/content/docs/reference/mcp-gateway.md
  - pkg/workflow/enclave_github_proxy_test.go
  - pkg/workflow/enclaves.go
  - pkg/workflow/mcp_gateway_config.go
comment_count: 2

Note

This comment is managed by comment memory.

It stores persistent context for this thread in the code block at the top of this comment.
Edit only the text inside the backtick fences; workflow metadata and the footer are regenerated automatically.

Learn more about comment memory

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 52 AIC · ⌖ 9.09 AIC · ⊞ 22.3K ·
Comment /review to run again

@github-actions github-actions Bot 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.

REQUEST_CHANGES

The enclave-only forcePublicRepos change itself makes sense, but the new compiler warning is not tied to the actual override state, so it now flags an explicitly supported opt-out path as broken.

Blocking theme

When a workflow combines a static GitHub enclave with primary tools.github and intentionally sets tools.github.private-to-public-flows: allow, buildMCPGatewayConfig already disables the runtime public-repos override. staticEnclaveGitHubScopeOverrideWarning does not account for that, so compilation still warns that the gateway will rewrite the scope to repos="public" and advises removing tools.github. That turns a valid configuration into a permanent false positive and makes the new diagnostic hard to trust.

Warning

Firewall blocked 1 domain

The following domain was blocked by the firewall during workflow execution:

  • github.com

To allow these domains, add them to the network.allowed list in your workflow frontmatter:

network:
  allowed:
    - defaults
    - "github.com"

See Network Configuration for more information.

🔎 Code quality review by PR Code Quality Reviewer · copilot · gpt54 · 52 AIC · ⌖ 9.09 AIC · ⊞ 22.3K
Comment /review to run again

Comment thread pkg/workflow/enclaves.go
if !enclaveGitHubIssuesEnabled(workflowData) || !primaryGitHubMCPEnabled(workflowData) {
return ""
}
return "enclaves: a static GitHub agent enclave is combined with primary 'tools.github'. In a public repository " +

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.

This warning is a false positive for the documented tools.github.private-to-public-flows: allow opt-out, because buildMCPGatewayConfig already emits forcePublicRepos: false for that configuration and the enclave keeps its declared scope.

💡 Why this blocks the change

staticEnclaveGitHubScopeOverrideWarning only checks "static enclave + primary tools.github". It never checks whether the workflow has already disabled the runtime override via private-to-public-flows: allow, so the compiler will still print "the enclave reads nothing" and tell authors to remove tools.github even when the chosen configuration is the supported escape hatch.

Please key this warning off the effective forcePublicRepos state instead of the raw tool combination, and add a regression test for tools.github + static enclave + private-to-public-flows: allow so the warning only appears when the override really stays enabled.

Comment thread pkg/workflow/enclaves.go
if !enclaveGitHubIssuesEnabled(workflowData) || !primaryGitHubMCPEnabled(workflowData) {
return ""
}
return "enclaves: a static GitHub agent enclave is combined with primary 'tools.github'. In a public repository " +

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.

This warning is emitted unconditionally for any static-enclave-plus-primary-tools.github workflow, but the breakage you describe only occurs in public repositories, so private-repo compiles now get a false alarm too.

💡 Why this blocks the change

The warning text says the gateway rewrites the scope to repos="public" and leaves the enclave reading nothing, but that runtime override only does that on public repositories. On a private repository, this exact configuration does not hit the stated failure mode, so emitting the warning at compile time as a guaranteed problem is inaccurate and trains users to ignore it.

Please either gate the diagnostic on a public-repository context when that is knowable, or weaken the message so it clearly states this is a public-repo-only hazard instead of a universal failure.

@github-actions github-actions Bot 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.

Reviewed with a correctness/security-first lens (backend compiler config change, not UI, so Impeccable's UI-focused modes weren't applicable — harden guidance on edge-state completeness was used instead).

Findings: none blocking.

  • forcePublicRepos is only forced to false when githubBackendIsStaticEnclaveDelegationOnly holds, and only when not already set from private-to-public-flows — explicit author config still wins. ✅
  • staticEnclaveGitHubScopeOverrideWarning correctly gates on both enclaveGitHubIssuesEnabled (covers both the CLI-issues profile and tools.github variants) and primaryGitHubMCPEnabled, and follows the existing console.FormatWarningMessageStderr + os.Stderr pattern used throughout pkg/workflow. ✅
  • New tests cover enclave-only, primary-GitHub-enabled, and no-enclave cases, plus the warning path — all pass locally (go test ./pkg/workflow/... -run 'TestBuildMCPGatewayConfigForcePublicReposForStaticEnclave|TestStaticEnclaveGitHubScopeOverrideWarning|TestGitHubGuardPoliciesFromStepSkipsEnclaveOnlyBackend|TestEnclaveGitHubToolsVersionGates'). ✅
  • Docs (experimental/enclaves.md, reference/mcp-gateway.md) and changeset accurately describe the new behavior. ✅

No inline comments needed.

🧵 Reviewed using Impeccable skills by Impeccable Skills Reviewer · copilot · sonnet50 · 39.6 AIC · ⌖ 13.6 AIC · ⊞ 8.4K

@github-actions github-actions Bot 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.

Skills-Based Review 🧠

Applied /codebase-design and /tdd — approving with one non-blocking observation.

📋 Key Themes & Highlights

Key Themes

  • Scope precisely bounded: The fix (forcePublicRepos: false for enclave-only GitHub backends) is gated by githubBackendIsStaticEnclaveDelegationOnly, which correctly requires tools.github: false on the primary agent. This mirrors the existing private-to-public-flows: allow opt-out pattern already in the codebase, keeping the change consistent with prior art rather than introducing a new mechanism.
  • Fail-loud instead of fail-silent: staticEnclaveGitHubScopeOverrideWarning covers the case the compile-time fix can't resolve automatically (primary + enclave both wanting GitHub access) by naming the exact discarded config path (enclaves[].agent.tools.github.allowed-repos). This is a good instance of turning a previously silent failure into an actionable compile-time warning.
  • Test coverage is solid: Three explicit buildMCPGatewayConfig cases (enclave-only, primary-enabled, no-enclave) plus a warning-emission test plus a lock-file substring assertion in the existing enclave-only compile test. All new/changed tests pass locally.
  • Minor gap (non-blocking): The dynamic-enclave delegation path (githubBackendIsDynamicDelegationOnly) appears to share the same forcePublicRepos-clobbers-scope risk, but this PR intentionally scopes the fix to the static enclave case. Left an inline comment suggesting a tracking issue.

Positive Highlights

  • forcePublicRepos == nil guard ensures explicit private-to-public-flows config always wins over the new auto-detection — no precedence surprises.
  • ✅ Docs (both enclaves.md and the mcp-gateway.md spec §4.1.3.8) were updated in the same PR, keeping the behavior change and its documentation in sync.
  • ✅ Changeset included.

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · copilot · sonnet50 · 183.9 AIC · ⌖ 16.1 AIC · ⊞ 10.4K
Comment /matt to run again

Comment thread pkg/workflow/enclaves.go
// which silently discards enclaves[].agent.tools.github.allowed-repos and leaves the enclave
// unable to read the declared private repositories.
func staticEnclaveGitHubScopeOverrideWarning(workflowData *WorkflowData) string {
if !enclaveGitHubIssuesEnabled(workflowData) || !primaryGitHubMCPEnabled(workflowData) {

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.

[/codebase-design] Good targeted fix — this warning correctly names the discarded config path instead of failing silently, consistent with the codebase's existing pattern (see console.FormatWarningMessageStderr in agent_validation.go, compiler.go). One gap worth flagging for a follow-up: the dynamic-enclave delegation path (githubBackendIsDynamicDelegationOnly) shares the same forcePublicRepos-clobbers-enclave-scope risk as the static path fixed here, but neither buildMCPGatewayConfig nor this warning covers it — combining a dynamic GitHub enclave with primary tools.github would silently rewrite the delegated identity's allow-only scope the same way. Not blocking this PR (out of its stated scope), but worth a tracking issue so the dynamic path isn't left with the same silent-failure gap this PR just closed for static enclaves.

@copilot please address this.

@lpcox

lpcox commented Sep 10, 2026

Copy link
Copy Markdown
Collaborator

@copilot address all review feedback

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

Copilot AI commented Sep 10, 2026

Copy link
Copy Markdown
Contributor Author

@copilot address all review feedback

Addressed all review feedback in a15abd4: compiler warning accounting, MCP-only documentation scope, and the remaining gateway/schema contract descriptions.

@lpcox
lpcox merged commit b22a4bd into main Sep 10, 2026
34 checks passed
@lpcox
lpcox deleted the copilot/fix-static-github-agent-enclave branch September 10, 2026 18:15
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This pull request is included in a new release.

Release: v0.89.3

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.

Static GitHub agent enclaves silently read nothing: forcePublicRepos overrides the enclave's allow-only guard, producing ungrounded answers

3 participants