feat: add write-sink guard policy to all non-GitHub MCP servers configured by gateway#21005
feat: add write-sink guard policy to all non-GitHub MCP servers configured by gateway#21005
Conversation
…gured by gateway Extend the write-sink guard policy (currently applied only to safe-outputs) to ALL non-GitHub MCP servers exposed by the MCP gateway. The policy is derived from the same GitHub guard-policy parameters (repos/min-integrity), ensuring that as guard policies are rolled out, only GitHub inputs will be filtered while outputs to non-GitHub servers are not restricted. Servers updated: playwright, serena, mcp-scripts, agentic-workflows, web-fetch, and all custom user-defined MCP tools. Both JSON format (for gateway/Claude/Copilot/Gemini) and TOML format (for Codex) are updated with guard policy rendering. Also adds a deriveWriteSinkGuardPolicyFromWorkflow helper and a comprehensive test file covering the new behavior. Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
|
@copilot update the pr to give an example for behavior when repos is an array of values, not just public or all |
The PR description now explains the array case. When tools:
github:
repos:
- "myorg/*" # owner wildcard
- "myorg/service-*" # prefix wildcard
- "otherorg/specific" # specific repo
min-integrity: approved
playwright: ...
my-custom-tool: ...Produces on every non-GitHub MCP server (TOML format): [mcp_servers.playwright."guard-policies"]
[mcp_servers.playwright."guard-policies".write-sink]
accept = ["private:myorg", "private:myorg/service-*", "private:otherorg/specific"]And in JSON format (gateway/Claude/Copilot/Gemini): "guard-policies": {
"write-sink": {
"accept": ["private:myorg", "private:myorg/service-*", "private:otherorg/specific"]
}
}Transformation rules per entry:
Note: GitHub's API is not accessible from this environment so the PR description itself couldn't be updated via API — the example is captured here in the comment. Warning Firewall rules blocked me from connecting to one or more addresses (expand for details)I tried to connect to the following addresses, but was blocked by firewall rules:
Extends the write-sink guard policy (currently applied only to safe-outputs) to ALL non-GitHub MCP servers exposed by the MCP gateway. The policy is derived from the same GitHub guard-policy parameters (
|
…1010) * Initial plan * fix: fix TypeScript type error in json_object_to_markdown.cjs Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Extends write-sink guard policies to all non-GitHub MCP servers configured by the gateway, ensuring non-GitHub outputs aren't restricted when GitHub guard policies are rolled out.
Changes:
- New
deriveWriteSinkGuardPolicyFromWorkflowhelper and new fields (WriteSinkGuardPolicies,GuardPolicies) to propagate guard policies through renderers - All built-in MCP server renderers (playwright, serena, mcp-scripts, agentic-workflows, web-fetch) and custom tool rendering updated to emit guard policies in both JSON and TOML formats
- All four engines (Claude, Copilot, Codex, Gemini) wired to derive and pass guard policies
- Minor JSDoc type annotation cleanup in
json_object_to_markdown.cjs
Reviewed changes
Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| pkg/workflow/mcp_github_config.go | New deriveWriteSinkGuardPolicyFromWorkflow helper |
| pkg/workflow/mcp_renderer_types.go | New WriteSinkGuardPolicies field on renderer options |
| pkg/workflow/mcp_config_types.go | New GuardPolicies field on MCPConfigRenderer |
| pkg/workflow/mcp_renderer_builtin.go | TOML/JSON guard policy rendering for built-in servers |
| pkg/workflow/mcp_config_playwright_renderer.go | Guard policy support in playwright JSON renderer |
| pkg/workflow/mcp_config_serena_renderer.go | Guard policy support in serena JSON renderer |
| pkg/workflow/mcp_scripts_renderer.go | Guard policy support in mcp-scripts JSON renderer |
| pkg/workflow/mcp_config_builtin.go | Guard policy support in agentic-workflows JSON renderer |
| pkg/workflow/fetch.go | Guard policy support in web-fetch renderer (JSON+TOML) |
| pkg/workflow/mcp_config_custom.go | Guard policy support in custom tool renderer |
| pkg/workflow/claude_mcp.go | Wire guard policies in Claude engine |
| pkg/workflow/copilot_mcp.go | Wire guard policies in Copilot engine |
| pkg/workflow/codex_mcp.go | Wire guard policies in Codex engine |
| pkg/workflow/gemini_mcp.go | Wire guard policies in Gemini engine |
| pkg/workflow/non_github_mcp_guard_policy_test.go | 21 new tests for guard policy derivation and rendering |
| pkg/workflow/mcp_config_comprehensive_test.go | Update existing tests for new function signatures |
| pkg/workflow/mcp_config_refactor_test.go | Update existing tests for new function signatures |
| pkg/workflow/fetch_test.go | Update existing tests for new function signatures |
| actions/setup/js/json_object_to_markdown.cjs | Minor JSDoc type cleanup |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
You can also share your feedback on Copilot code review. Take the survey.
| Format: "toml", | ||
| IsLast: isLast, | ||
| ActionMode: GetActionModeFromWorkflowData(workflowData), | ||
| WriteSinkGuardPolicies: deriveWriteSinkGuardPolicyFromWorkflow(workflowData), |
…expansion - cli.md: note that gh aw audit and add-wizard auto-detect the GHES host from the git remote (from #20973), so GH_HOST is not required manually - github-tools.md: update Safe Outputs Integration section to reflect that write-sink guard policies are now derived for ALL non-GitHub MCP servers (playwright, serena, mcp-scripts, agentic-workflows, web-fetch, custom tools), not only safe-outputs (from #21005) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Extends the write-sink guard policy (currently applied only to safe-outputs) to ALL non-GitHub MCP servers exposed by the MCP gateway. The policy is derived from the same GitHub guard-policy parameters (
repos/min-integrity), ensuring that as guard policies are rolled out, only GitHub inputs will be filtered while outputs to non-GitHub servers are not restricted.Background
Previously, only
safe-outputshad a write-sink guard policy automatically derived from the GitHub guard-policy. This change makes this the default configuration for all non-GitHub MCP servers, as described in the issue: "Just as safeoutputs is configured as a write-sink to allow all github data to pass, this must also be the default configuration for any non-github mcp server exposed by the gateway."Changes
New infrastructure
deriveWriteSinkGuardPolicyFromWorkflow- Helper that derives write-sink guard policies from workflow's GitHub guard-policy configuration (same logic asderiveSafeOutputsGuardPolicyFromGitHub)MCPRendererOptions.WriteSinkGuardPolicies- New field that propagates derived guard policies to all built-in server renderersMCPConfigRenderer.GuardPolicies- New field that propagates guard policies throughrenderSharedMCPConfigfor custom toolsServers updated (both JSON and TOML formats)
renderPlaywrightMCPConfigWithOptions+ TOML wrapperrenderSerenaMCPConfigWithOptions+ TOML wrapperrenderMCPScriptsMCPConfigWithOptions+ TOML wrapperrenderAgenticWorkflowsMCPConfigWithOptions+ TOML wrapperrenderMCPFetchServerConfig(JSON + TOML)renderSharedMCPConfig(handles both JSON and TOML in one place)Engine wiring
All 4 engines (Claude, Copilot, Codex, Gemini) now pass
WriteSinkGuardPolicieswhen creating renderers.Behavior
Simple case:
repos: allorrepos: publicWhen
reposisallorpublic, all non-GitHub MCP servers receiveaccept: ["*"](allow all write operations):Array case:
reposas a list of patternsWhen
reposis an array, theacceptpatterns are derived per-entry and combined. Transformation rules per entry:owner/*→private:owner(owner wildcard: strips the/*suffix)owner/prefix-*→private:owner/prefix-*(prefix wildcard: keeps as-is withprivate:prefix)owner/repo→private:owner/repo(specific repo: keeps as-is withprivate:prefix)Produces on every non-GitHub MCP server (TOML format):
And in JSON format (used by the gateway for Claude/Copilot/Gemini/Codex):
When no GitHub guard policy is configured, no write-sink guard policies are added (existing behavior unchanged).
Testing
Added
non_github_mcp_guard_policy_test.gowith 21 new tests covering:deriveWriteSinkGuardPolicyFromWorkflowhelperMCPConfigRendererUnifiedSecurity Summary
No new security vulnerabilities introduced. The write-sink guard policy is a passthrough configuration that allows data to flow to non-GitHub servers. CodeQL analysis found no issues with the changes.
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.