From 9c6bb95584e9ab20f137a2b85d57b825b473a4b5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 07:53:34 +0000 Subject: [PATCH 1/4] Initial plan From aeaa2a56c552b4de919e17674843ca93686f2e5a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 07:58:23 +0000 Subject: [PATCH 2/4] Plan: Add if/then conditional validation for field requirements Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- .github/workflows/issue-classifier.lock.yml | 2 +- .github/workflows/release.lock.yml | 6 +++--- .github/workflows/stale-repo-identifier.lock.yml | 2 +- .github/workflows/super-linter.lock.yml | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index a22d440eb5c..86c01e6d76f 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -2211,7 +2211,7 @@ jobs: path: /tmp/gh-aw/aw_info.json if-no-files-found: warn - name: Run AI Inference - uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v2.0.4 + uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v1 env: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index 6f307c8c770..f5a0cc548d6 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -6031,13 +6031,13 @@ jobs: - name: Download Go modules run: go mod download - name: Generate SBOM (SPDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 with: artifact-name: sbom.spdx.json format: spdx-json output-file: sbom.spdx.json - name: Generate SBOM (CycloneDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 with: artifact-name: sbom.cdx.json format: cyclonedx-json @@ -6244,7 +6244,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Release with gh-extension-precompile - uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2.1.0 + uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2 with: build_script_override: scripts/build-release.sh go_version_file: go.mod diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index 2917200924f..a2dc0fc2462 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -176,7 +176,7 @@ jobs: ORGANIZATION: ${{ env.ORGANIZATION }} id: stale-repos name: Run stale_repos tool - uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3.0.2 + uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3 - env: INACTIVE_REPOS: ${{ steps.stale-repos.outputs.inactiveRepos }} name: Save stale repos output diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index 2324c85f388..27afaf48be3 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -6161,7 +6161,7 @@ jobs: persist-credentials: false - name: Super-linter id: super-linter - uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.3.1 + uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.2.1 env: CREATE_LOG_FILE: "true" DEFAULT_BRANCH: main From a4e6169a2ff311b40c6dd86ac0e9d72f4f8e6ab8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 08:14:40 +0000 Subject: [PATCH 3/4] Add conditional validation for field requirements in JSON schema - Add if/then constraint for MCP containers in strict mode requiring network - Add if/then constraint for write permissions requiring safe-outputs in strict mode - Add if/then constraint for sandbox-runtime requiring feature flag - Add if/then constraint for UV packages requiring network access - Add 'network' field to known MCP configuration properties - Rebuild binary with updated embedded schema Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- .github/workflows/issue-classifier.lock.yml | 2 +- .github/workflows/release.lock.yml | 6 +- .../workflows/stale-repo-identifier.lock.yml | 2 +- .github/workflows/super-linter.lock.yml | 2 +- pkg/parser/schemas/main_workflow_schema.json | 218 ++++++++++++++++++ pkg/workflow/mcp-config.go | 1 + pkg/workflow/mcp_config_validation.go | 3 +- 7 files changed, 227 insertions(+), 7 deletions(-) diff --git a/.github/workflows/issue-classifier.lock.yml b/.github/workflows/issue-classifier.lock.yml index 86c01e6d76f..a22d440eb5c 100644 --- a/.github/workflows/issue-classifier.lock.yml +++ b/.github/workflows/issue-classifier.lock.yml @@ -2211,7 +2211,7 @@ jobs: path: /tmp/gh-aw/aw_info.json if-no-files-found: warn - name: Run AI Inference - uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v1 + uses: actions/ai-inference@334892bb203895caaed82ec52d23c1ed9385151e # v2.0.4 env: GH_AW_MCP_CONFIG: /tmp/gh-aw/mcp-config/mcp-servers.json GH_AW_PROMPT: /tmp/gh-aw/aw-prompts/prompt.txt diff --git a/.github/workflows/release.lock.yml b/.github/workflows/release.lock.yml index f5a0cc548d6..6f307c8c770 100644 --- a/.github/workflows/release.lock.yml +++ b/.github/workflows/release.lock.yml @@ -6031,13 +6031,13 @@ jobs: - name: Download Go modules run: go mod download - name: Generate SBOM (SPDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 with: artifact-name: sbom.spdx.json format: spdx-json output-file: sbom.spdx.json - name: Generate SBOM (CycloneDX format) - uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.10 + uses: anchore/sbom-action@43a17d6e7add2b5535efe4dcae9952337c479a93 # v0.20.11 with: artifact-name: sbom.cdx.json format: cyclonedx-json @@ -6244,7 +6244,7 @@ jobs: fetch-depth: 0 persist-credentials: false - name: Release with gh-extension-precompile - uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2 + uses: cli/gh-extension-precompile@9e2237c30f869ad3bcaed6a4be2cd43564dd421b # v2.1.0 with: build_script_override: scripts/build-release.sh go_version_file: go.mod diff --git a/.github/workflows/stale-repo-identifier.lock.yml b/.github/workflows/stale-repo-identifier.lock.yml index a2dc0fc2462..2917200924f 100644 --- a/.github/workflows/stale-repo-identifier.lock.yml +++ b/.github/workflows/stale-repo-identifier.lock.yml @@ -176,7 +176,7 @@ jobs: ORGANIZATION: ${{ env.ORGANIZATION }} id: stale-repos name: Run stale_repos tool - uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3 + uses: github/stale-repos@a21e55567b83cf3c3f3f9085d3038dc6cee02598 # v3.0.2 - env: INACTIVE_REPOS: ${{ steps.stale-repos.outputs.inactiveRepos }} name: Save stale repos output diff --git a/.github/workflows/super-linter.lock.yml b/.github/workflows/super-linter.lock.yml index 27afaf48be3..2324c85f388 100644 --- a/.github/workflows/super-linter.lock.yml +++ b/.github/workflows/super-linter.lock.yml @@ -6161,7 +6161,7 @@ jobs: persist-credentials: false - name: Super-linter id: super-linter - uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.2.1 + uses: super-linter/super-linter@47984f49b4e87383eed97890fe2dca6063bbd9c3 # v8.3.1 env: CREATE_LOG_FILE: "true" DEFAULT_BRANCH: main diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 510479189b5..4eeabebef25 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -5136,6 +5136,224 @@ } } } + }, + { + "$comment": "Strict mode: MCP containers require network configuration", + "if": { + "properties": { + "strict": { + "const": true + }, + "mcp-servers": { + "type": "object", + "patternProperties": { + ".*": { + "type": "object", + "anyOf": [ + { + "required": ["container"] + }, + { + "properties": { + "type": { + "enum": ["stdio", "local"] + } + }, + "required": ["type", "container"] + } + ] + } + } + } + }, + "required": ["strict", "mcp-servers"] + }, + "then": { + "properties": { + "mcp-servers": { + "patternProperties": { + ".*": { + "if": { + "anyOf": [ + { + "required": ["container"] + }, + { + "properties": { + "type": { + "enum": ["stdio", "local"] + } + }, + "required": ["type", "container"] + } + ] + }, + "then": { + "required": ["network"] + } + } + } + } + } + } + }, + { + "$comment": "Strict mode: Write permissions require safe-outputs configuration", + "if": { + "properties": { + "strict": { + "const": true + }, + "permissions": { + "type": "object", + "anyOf": [ + { + "properties": { + "contents": { + "const": "write" + } + }, + "required": ["contents"] + }, + { + "properties": { + "issues": { + "const": "write" + } + }, + "required": ["issues"] + }, + { + "properties": { + "pull-requests": { + "const": "write" + } + }, + "required": ["pull-requests"] + } + ] + } + }, + "required": ["strict", "permissions"] + }, + "then": { + "required": ["safe-outputs"] + } + }, + { + "$comment": "Sandbox-runtime requires feature flag", + "if": { + "anyOf": [ + { + "properties": { + "sandbox": { + "const": "sandbox-runtime" + } + }, + "required": ["sandbox"] + }, + { + "properties": { + "sandbox": { + "type": "object", + "properties": { + "type": { + "const": "sandbox-runtime" + } + }, + "required": ["type"] + } + }, + "required": ["sandbox"] + }, + { + "properties": { + "sandbox": { + "type": "object", + "properties": { + "agent": { + "type": "object", + "properties": { + "type": { + "const": "sandbox-runtime" + } + }, + "required": ["type"] + } + }, + "required": ["agent"] + } + }, + "required": ["sandbox"] + } + ] + }, + "then": { + "properties": { + "features": { + "type": "object", + "properties": { + "sandbox-runtime": { + "const": true + } + }, + "required": ["sandbox-runtime"] + } + }, + "required": ["features"] + } + }, + { + "$comment": "UV packages require network access with PyPI", + "if": { + "properties": { + "runtimes": { + "type": "object", + "properties": { + "uv": { + "type": "object" + } + }, + "required": ["uv"] + } + }, + "required": ["runtimes"] + }, + "then": { + "anyOf": [ + { + "properties": { + "network": { + "type": "object", + "properties": { + "allowed": { + "type": "array", + "contains": { + "enum": ["pypi.org", "python", "*"] + } + } + }, + "required": ["allowed"] + } + }, + "required": ["network"] + }, + { + "properties": { + "network": { + "type": "object", + "properties": { + "mode": { + "const": "defaults" + } + }, + "required": ["mode"] + } + }, + "required": ["network"] + } + ] + } } ], "$defs": { diff --git a/pkg/workflow/mcp-config.go b/pkg/workflow/mcp-config.go index 067860f96af..cc4b7bb483c 100644 --- a/pkg/workflow/mcp-config.go +++ b/pkg/workflow/mcp-config.go @@ -794,6 +794,7 @@ func getMCPConfig(toolConfig map[string]any, toolName string) (*parser.MCPServer "entrypointArgs": true, "env": true, "proxy-args": true, + "network": true, "url": true, "headers": true, "registry": true, diff --git a/pkg/workflow/mcp_config_validation.go b/pkg/workflow/mcp_config_validation.go index 7d235398cfa..998b7e53684 100644 --- a/pkg/workflow/mcp_config_validation.go +++ b/pkg/workflow/mcp_config_validation.go @@ -118,7 +118,7 @@ func getRawMCPConfig(toolConfig map[string]any) (map[string]any, error) { // to add custom arguments without triggering custom MCP tool processing logic. Including "args" // would incorrectly classify built-in tools as custom MCP tools, changing their processing behavior // and causing validation errors. - mcpFields := []string{"type", "url", "command", "container", "env", "headers"} + mcpFields := []string{"type", "url", "command", "container", "env", "headers", "network"} // List of all known tool config fields (not just MCP) knownToolFields := map[string]bool{ @@ -132,6 +132,7 @@ func getRawMCPConfig(toolConfig map[string]any) (map[string]any, error) { "args": true, "entrypointArgs": true, "proxy-args": true, + "network": true, // for container-based MCP servers "registry": true, "allowed": true, "mode": true, // for github tool From ee5eb4b5b92e68601392fef2c4cad29b76ee66c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 25 Dec 2025 08:18:47 +0000 Subject: [PATCH 4/4] Final validation: All conditional schema validations working correctly - Verified all four conditional validations catch violations correctly - Verified valid configurations still compile successfully - All MCP, Schema, and Strict mode tests pass - Pre-existing test failure in TestCodexAIConfiguration is unrelated to changes Co-authored-by: mnkiefer <8320933+mnkiefer@users.noreply.github.com> --- pkg/parser/schemas/main_workflow_schema.json | 35 ++++---------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 4eeabebef25..7f25a0117c8 100644 --- a/pkg/parser/schemas/main_workflow_schema.json +++ b/pkg/parser/schemas/main_workflow_schema.json @@ -285,10 +285,7 @@ }, { "not": { - "anyOf": [ - { "required": ["branches"] }, - { "required": ["branches-ignore"] } - ] + "anyOf": [{ "required": ["branches"] }, { "required": ["branches-ignore"] }] } } ], @@ -305,10 +302,7 @@ }, { "not": { - "anyOf": [ - { "required": ["paths"] }, - { "required": ["paths-ignore"] } - ] + "anyOf": [{ "required": ["paths"] }, { "required": ["paths-ignore"] }] } } ] @@ -431,10 +425,7 @@ }, { "not": { - "anyOf": [ - { "required": ["branches"] }, - { "required": ["branches-ignore"] } - ] + "anyOf": [{ "required": ["branches"] }, { "required": ["branches-ignore"] }] } } ], @@ -451,10 +442,7 @@ }, { "not": { - "anyOf": [ - { "required": ["paths"] }, - { "required": ["paths-ignore"] } - ] + "anyOf": [{ "required": ["paths"] }, { "required": ["paths-ignore"] }] } } ] @@ -669,10 +657,7 @@ }, { "not": { - "anyOf": [ - { "required": ["branches"] }, - { "required": ["branches-ignore"] } - ] + "anyOf": [{ "required": ["branches"] }, { "required": ["branches-ignore"] }] } } ] @@ -996,10 +981,7 @@ }, { "not": { - "anyOf": [ - { "required": ["branches"] }, - { "required": ["branches-ignore"] } - ] + "anyOf": [{ "required": ["branches"] }, { "required": ["branches-ignore"] }] } } ], @@ -1016,10 +998,7 @@ }, { "not": { - "anyOf": [ - { "required": ["paths"] }, - { "required": ["paths-ignore"] } - ] + "anyOf": [{ "required": ["paths"] }, { "required": ["paths-ignore"] }] } } ]