feat: add force-public-repos runtime check to proxy mode#8948
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a defense-in-depth “force public repos” runtime check to awmg proxy, mirroring the unified MCP gateway behavior, so a miscompiled allow-only policy can’t accidentally permit private-repo reads in public-repo workflows.
Changes:
- Resolve an “effective” proxy guard policy by optionally rewriting the allow-only
reposscope to"public"when the workflow repo is confirmed public via the GitHub REST API. - Add
proxyForcePublicReposIfNeededhelper implementing opt-out + fail-open semantics and handling canonical/legacy allow-only keys.
Show a summary per file
| File | Description |
|---|---|
| internal/cmd/proxy.go | Adds runtime repo-visibility verification and rewrites the proxy’s guard policy to force repos="public" when appropriate. |
Review details
Tip
Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
- Files reviewed: 1/1 changed files
- Comments generated: 3
- Review effort level: Low
| vis, err := githubhttp.FetchRepoVisibility(ctx, apiURL, nwo, "token "+authToken) | ||
| if err != nil { | ||
| logger.LogWarn("difc", "forcePublicRepos: failed to determine visibility for %s (fail-open): %v", nwo, err) | ||
| return policyJSON | ||
| } |
| if allowOnly == nil { | ||
| policyMap["allow-only"] = map[string]interface{}{ | ||
| "repos": "public", | ||
| "min-integrity": "none", | ||
| } | ||
| } else { | ||
| allowOnly["repos"] = "public" | ||
| } |
| // Defense-in-depth: force repos="public" when running in a public repository. | ||
| // This overrides the compiled policy to prevent agents from reading private | ||
| // repos, even if the compiler misconfigured the allow-only scope. | ||
| effectivePolicy := proxyPolicy | ||
| if effectivePolicy != "" { | ||
| effectivePolicy = proxyForcePublicReposIfNeeded(ctx, effectivePolicy, token, apiURL) | ||
| } |
When the workflow runs in a public repo (GITHUB_REPOSITORY is public), the proxy now overrides the allow-only policy to repos="public" before passing it to the WASM guard. This prevents agents from reading private repos through the gh CLI proxy, even if the compiler passed a permissive policy. The override can be explicitly disabled via: - MCP_GATEWAY_FORCE_PUBLIC_REPOS=false environment variable Fail-open semantics: if GITHUB_REPOSITORY is unset, no token is available, or the API call fails, the compiled policy is used as-is. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
f07dde0 to
e9b4156
Compare
|
@copilot address review feedback |
Addressed all three review comments in commit
|
Five integration tests covering the --force-public-repos flag: - Public workflow repo → forces repos=public override - --force-public-repos=false flag → disables override - MCP_GATEWAY_FORCE_PUBLIC_REPOS=false env var → disables override - No GITHUB_REPOSITORY → no override applied - Private workflow repo → no override applied Tests require WASM guard (skipped gracefully when unavailable). Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
db9e94b to
d94dab3
Compare
Summary
Adds the same
forcePublicReposdefense-in-depth runtime check to the CLI proxy (awmg proxy) that already exists in the MCP gateway (unified mode).Problem
The proxy receives its allow-only policy as a pre-built
--policyJSON string from the compiler. If the compiler misconfigures the policy (e.g.,repos: "all"when the workflow repo is public), the proxy would trust it and allow the agent to read private repos through theghCLI.Solution
Before passing the policy to the WASM guard, the proxy now:
GITHUB_REPOSITORYGET /repos/{owner}/{repo}to verify visibilityreposto"public"in the allow-only policyThis prevents agents in public-repo workflows from reading private repos, regardless of what policy the compiler passed.
Opt-out
Set
MCP_GATEWAY_FORCE_PUBLIC_REPOS=falseto disable (set by the compiler whenprivate-to-public-flows: allowis declared in workflow frontmatter).Fail-open semantics
The override is skipped when:
MCP_GATEWAY_FORCE_PUBLIC_REPOS=falseGITHUB_REPOSITORYis not setIn these cases, the compiled policy is used as-is.
Companion PR
forcePublicReposand sink-visibility