diff --git a/pkg/parser/schemas/main_workflow_schema.json b/pkg/parser/schemas/main_workflow_schema.json index 510479189b..7f25a0117c 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"] }] } } ] @@ -5136,6 +5115,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 067860f96a..cc4b7bb483 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 7d235398cf..998b7e5368 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