diff --git a/.github/workflows/daily-issues-report.lock.yml b/.github/workflows/daily-issues-report.lock.yml index a71ff7dc364..ff82e412275 100644 --- a/.github/workflows/daily-issues-report.lock.yml +++ b/.github/workflows/daily-issues-report.lock.yml @@ -31,7 +31,7 @@ # - shared/reporting.md # - shared/trends.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ec9eeff0e8692f0d6a1123216fcdaecdb21e7e322d54f0c1f633cf9b724d3068"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"0b2b5a8686d1b1cbb7ae3b1539786c390d00c6b808d981771054a8a1c24c581b"} name: "Daily Issues Report Generator" "on": diff --git a/.github/workflows/daily-issues-report.md b/.github/workflows/daily-issues-report.md index 49e335db53e..c562df375f8 100644 --- a/.github/workflows/daily-issues-report.md +++ b/.github/workflows/daily-issues-report.md @@ -10,8 +10,6 @@ permissions: engine: codex strict: true tracker-id: daily-issues-report -features: - dangerous-permissions-write: true tools: github: lockdown: true diff --git a/.github/workflows/daily-observability-report.lock.yml b/.github/workflows/daily-observability-report.lock.yml index 6d72d66a429..b3b6447ca38 100644 --- a/.github/workflows/daily-observability-report.lock.yml +++ b/.github/workflows/daily-observability-report.lock.yml @@ -27,7 +27,7 @@ # Imports: # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"57d943dc614a1300ac3a4e91c1515e029ccdc78e85a29ef78ba43867f1e85500"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"1b990129663822b2a2ec35c48272d37d9b5fd2588701da99710163ff9f98f551"} name: "Daily Observability Report for AWF Firewall and MCP Gateway" "on": diff --git a/.github/workflows/daily-observability-report.md b/.github/workflows/daily-observability-report.md index 55affc77392..f206a17ff89 100644 --- a/.github/workflows/daily-observability-report.md +++ b/.github/workflows/daily-observability-report.md @@ -10,8 +10,6 @@ permissions: engine: codex strict: true tracker-id: daily-observability-report -features: - dangerous-permissions-write: true tools: github: toolsets: [default, discussions, actions] diff --git a/.github/workflows/daily-performance-summary.lock.yml b/.github/workflows/daily-performance-summary.lock.yml index 66583c7beb2..d037278f0d4 100644 --- a/.github/workflows/daily-performance-summary.lock.yml +++ b/.github/workflows/daily-performance-summary.lock.yml @@ -29,7 +29,7 @@ # - shared/reporting.md # - shared/trending-charts-simple.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"ed7874fd2663e00d4fd6afb295903c6e19f62eaabcd9cb7d9ebfca25e38f0f7f"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"2756dfa16e5aae6fb4bc2d62922725b39130906d8db05fea13dc60b7b1b11b04"} name: "Daily Project Performance Summary Generator (Using Safe Inputs)" "on": diff --git a/.github/workflows/daily-performance-summary.md b/.github/workflows/daily-performance-summary.md index 5b8bf5a499f..31883fa830e 100644 --- a/.github/workflows/daily-performance-summary.md +++ b/.github/workflows/daily-performance-summary.md @@ -12,8 +12,6 @@ permissions: engine: codex strict: true tracker-id: daily-performance-summary -features: - dangerous-permissions-write: true tools: github: toolsets: [default, discussions] diff --git a/.github/workflows/example-permissions-warning.lock.yml b/.github/workflows/example-permissions-warning.lock.yml index 2fc7cb6e13c..9d0bf30393d 100644 --- a/.github/workflows/example-permissions-warning.lock.yml +++ b/.github/workflows/example-permissions-warning.lock.yml @@ -23,7 +23,7 @@ # # Example workflow demonstrating proper permission provisioning and security best practices # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"94ffd5b85d76a2be5b3602a2babffa5a24d9e2bf59e74b4a81355902bdf06e01"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"cbc025e1319832edb0b85151db2c36cdde748e467faf1d0d20c646d33e8a0542"} name: "Example: Properly Provisioned Permissions" "on": @@ -325,6 +325,7 @@ jobs: "env": { "GITHUB_LOCKDOWN_MODE": "$GITHUB_MCP_LOCKDOWN", "GITHUB_PERSONAL_ACCESS_TOKEN": "\${GITHUB_MCP_SERVER_TOKEN}", + "GITHUB_READ_ONLY": "1", "GITHUB_TOOLSETS": "repos,issues,pull_requests" } } diff --git a/.github/workflows/example-permissions-warning.md b/.github/workflows/example-permissions-warning.md index 15631f3c420..e1c377d497d 100644 --- a/.github/workflows/example-permissions-warning.md +++ b/.github/workflows/example-permissions-warning.md @@ -10,20 +10,18 @@ permissions: tools: github: toolsets: [repos, issues, pull_requests] - read-only: false strict: false -features: - dangerous-permissions-write: true --- # Example: Properly Provisioned Permissions This workflow demonstrates properly configured permissions for GitHub toolsets. -The workflow uses three GitHub toolsets with appropriate write permissions: -- The `repos` toolset requires `contents: write` for repository operations -- The `issues` toolset requires `issues: write` for issue management -- The `pull_requests` toolset requires `pull-requests: write` for PR operations +The GitHub MCP server always operates in read-only mode. The workflow uses three +GitHub toolsets with read permissions: +- The `repos` toolset uses `contents: read` for repository operations +- The `issues` toolset uses `issues: read` for issue management +- The `pull_requests` toolset uses `pull-requests: read` for PR operations All required permissions are properly declared in the frontmatter, so this workflow compiles without warnings and can execute successfully when dispatched. diff --git a/.github/workflows/org-health-report.lock.yml b/.github/workflows/org-health-report.lock.yml index f0b1fac5581..c44ec36451e 100644 --- a/.github/workflows/org-health-report.lock.yml +++ b/.github/workflows/org-health-report.lock.yml @@ -29,7 +29,7 @@ # - shared/python-dataviz.md # - shared/reporting.md # -# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"090051691a90fe9bffa581e7cec2895e16abec73e72d456021b9467082ff45f7"} +# gh-aw-metadata: {"schema_version":"v1","frontmatter_hash":"69c42ab10b276922ff8a54f27c02a0dacef4ccf036124cd8aeba296e1e7062b2"} name: "Organization Health Report" "on": diff --git a/.github/workflows/org-health-report.md b/.github/workflows/org-health-report.md index a96b8d2a492..f191a65a463 100644 --- a/.github/workflows/org-health-report.md +++ b/.github/workflows/org-health-report.md @@ -30,8 +30,6 @@ safe-outputs: upload-asset: timeout-minutes: 60 strict: true -features: - dangerous-permissions-write: true network: allowed: - defaults diff --git a/pkg/cli/codemod_schema_file_test.go b/pkg/cli/codemod_schema_file_test.go index 6992c0607b5..5213415a583 100644 --- a/pkg/cli/codemod_schema_file_test.go +++ b/pkg/cli/codemod_schema_file_test.go @@ -75,7 +75,7 @@ on: engine: copilot permissions: contents: read - issues: write + issues: read --- # Complex Workflow diff --git a/pkg/cli/commands_compile_workflow_test.go b/pkg/cli/commands_compile_workflow_test.go index 9e120ad32db..c989ce02009 100644 --- a/pkg/cli/commands_compile_workflow_test.go +++ b/pkg/cli/commands_compile_workflow_test.go @@ -66,12 +66,10 @@ on: schedule: - cron: "0 9 * * 1" permissions: - contents: write + contents: read issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true --- # Verbose Test Workflow diff --git a/pkg/cli/compile_security_benchmark_test.go b/pkg/cli/compile_security_benchmark_test.go index ec508a61659..ac6f364ed32 100644 --- a/pkg/cli/compile_security_benchmark_test.go +++ b/pkg/cli/compile_security_benchmark_test.go @@ -26,10 +26,8 @@ on: types: [opened, synchronize] permissions: contents: read - pull-requests: write + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true strict: false tools: github: @@ -77,10 +75,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false tools: github: @@ -174,8 +170,8 @@ on: types: [opened, synchronize, reopened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: id: copilot max-turns: 5 @@ -243,10 +239,8 @@ on: types: [opened, synchronize] permissions: contents: read - pull-requests: write + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true strict: false tools: github: @@ -295,10 +289,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false tools: github: @@ -366,9 +358,9 @@ on: - production permissions: contents: read - issues: write - pull-requests: write - deployments: write + issues: read + pull-requests: read + deployments: read engine: id: copilot max-turns: 10 diff --git a/pkg/cli/update_command_test.go b/pkg/cli/update_command_test.go index 03414c4eb3d..24480c6f5bd 100644 --- a/pkg/cli/update_command_test.go +++ b/pkg/cli/update_command_test.go @@ -314,7 +314,7 @@ Base content.` on: push permissions: contents: read - issues: write + issues: read source: test/repo/workflow.md@v1.0.0 --- @@ -327,7 +327,7 @@ Base content with local notes.` on: push permissions: contents: read - pull-requests: write + pull-requests: read --- # Test Workflow diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 7e3986e5eff..a53e205e1d0 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -624,8 +624,6 @@ const ( SafeInputsFeatureFlag FeatureFlag = "safe-inputs" // MCPGatewayFeatureFlag is the feature flag name for enabling MCP gateway MCPGatewayFeatureFlag FeatureFlag = "mcp-gateway" - // DangerousPermissionsWriteFeatureFlag is the feature flag name for allowing write permissions - DangerousPermissionsWriteFeatureFlag FeatureFlag = "dangerous-permissions-write" // DisableXPIAPromptFeatureFlag is the feature flag name for disabling XPIA prompt DisableXPIAPromptFeatureFlag FeatureFlag = "disable-xpia-prompt" // CopilotRequestsFeatureFlag is the feature flag name for enabling copilot-requests mode. diff --git a/pkg/constants/constants_test.go b/pkg/constants/constants_test.go index 0d35d74e26f..eca048659ee 100644 --- a/pkg/constants/constants_test.go +++ b/pkg/constants/constants_test.go @@ -322,7 +322,6 @@ func TestFeatureFlagConstants(t *testing.T) { }{ {"SafeInputsFeatureFlag", SafeInputsFeatureFlag, "safe-inputs"}, {"MCPGatewayFeatureFlag", MCPGatewayFeatureFlag, "mcp-gateway"}, - {"DangerousPermissionsWriteFeatureFlag", DangerousPermissionsWriteFeatureFlag, "dangerous-permissions-write"}, {"DisableXPIAPromptFeatureFlag", DisableXPIAPromptFeatureFlag, "disable-xpia-prompt"}, } diff --git a/pkg/parser/mcp.go b/pkg/parser/mcp.go index c4d038e887a..df4beec1ce0 100644 --- a/pkg/parser/mcp.go +++ b/pkg/parser/mcp.go @@ -256,7 +256,6 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) // Check for custom GitHub configuration to determine mode (local vs remote) var useRemote bool var customGitHubToken string - var readOnly bool if toolConfig, ok := toolValue.(map[string]any); ok { // Check if mode is specified (remote or local) @@ -272,13 +271,6 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) customGitHubToken = tokenStr } } - - // Check for read-only mode - if readOnlyField, hasReadOnly := toolConfig["read-only"]; hasReadOnly { - if readOnlyBool, ok := readOnlyField.(bool); ok { - readOnly = readOnlyBool - } - } } var config MCPServerConfig @@ -300,10 +292,8 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) config.Env["GITHUB_TOKEN"] = customGitHubToken } - // Add X-MCP-Readonly header if read-only mode is enabled - if readOnly { - config.Headers["X-MCP-Readonly"] = "true" - } + // Always enforce read-only mode for GitHub MCP server + config.Headers["X-MCP-Readonly"] = "true" } else { // Handle GitHub MCP server - use local/Docker by default config = MCPServerConfig{ @@ -312,6 +302,7 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", // Always enforce read-only mode "ghcr.io/github/github-mcp-server:" + string(constants.DefaultGitHubMCPServerVersion), }, Env: make(map[string]string), @@ -331,12 +322,6 @@ func processBuiltinMCPTool(toolName string, toolValue any, serverFilter string) // Check for custom GitHub configuration if toolConfig, ok := toolValue.(map[string]any); ok { - // Check for read-only mode (only applicable in local/Docker mode) - if !useRemote && readOnly { - // When read-only is true, inline GITHUB_READ_ONLY=1 in docker args - config.Args = append(config.Args[:5], append([]string{"-e", "GITHUB_READ_ONLY=1"}, config.Args[5:]...)...) - } - if allowed, hasAllowed := toolConfig["allowed"]; hasAllowed { if allowedSlice, ok := allowed.([]any); ok { for _, item := range allowedSlice { diff --git a/pkg/parser/mcp_test.go b/pkg/parser/mcp_test.go index e0bd82427fa..06bbe5c1cad 100644 --- a/pkg/parser/mcp_test.go +++ b/pkg/parser/mcp_test.go @@ -48,7 +48,7 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, { - name: "GitHub tool with read-only false", + name: "GitHub tool with read-only false (always enforced as read-only)", frontmatter: map[string]any{ "tools": map[string]any{ "github": map[string]any{ @@ -61,6 +61,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:" + string(constants.DefaultGitHubMCPServerVersion), }, Env: map[string]string{ @@ -71,6 +72,27 @@ func TestExtractMCPConfigurations(t *testing.T) { }, }, }, + { + name: "GitHub tool with boolean true (shorthand)", + frontmatter: map[string]any{ + "tools": map[string]any{ + "github": true, + }, + }, + expected: []MCPServerConfig{ + {BaseMCPServerConfig: types.BaseMCPServerConfig{Type: "docker", + Command: "docker", + Args: []string{ + "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", + "ghcr.io/github/github-mcp-server:" + string(constants.DefaultGitHubMCPServerVersion), + }, + Env: map[string]string{ + "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN_REQUIRED}", + }}, Name: "github", + }, + }, + }, { name: "GitHub tool without read-only (default behavior)", frontmatter: map[string]any{ @@ -83,6 +105,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:" + string(constants.DefaultGitHubMCPServerVersion), }, Env: map[string]string{ @@ -119,6 +142,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:" + string(constants.DefaultGitHubMCPServerVersion), }, Env: map[string]string{"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN_REQUIRED}"}}, Name: "github", @@ -142,6 +166,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:latest", }, Env: map[string]string{"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN_REQUIRED}"}}, Name: "github", @@ -164,6 +189,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:20", }, Env: map[string]string{"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN_REQUIRED}"}}, Name: "github", @@ -186,6 +212,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:3.11", }, Env: map[string]string{"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN_REQUIRED}"}}, Name: "github", @@ -317,6 +344,7 @@ func TestExtractMCPConfigurations(t *testing.T) { Command: "docker", Args: []string{ "run", "-i", "--rm", "-e", "GITHUB_PERSONAL_ACCESS_TOKEN", + "-e", "GITHUB_READ_ONLY=1", "ghcr.io/github/github-mcp-server:" + string(constants.DefaultGitHubMCPServerVersion), }, Env: map[string]string{"GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN_REQUIRED}"}}, Name: "github", diff --git a/pkg/workflow/action_sha_validation_test.go b/pkg/workflow/action_sha_validation_test.go index c4bcb9b0d37..7922187f444 100644 --- a/pkg/workflow/action_sha_validation_test.go +++ b/pkg/workflow/action_sha_validation_test.go @@ -88,11 +88,9 @@ on: issues: types: [opened] engine: copilot -features: - dangerous-permissions-write: true permissions: contents: read - issues: write + issues: read pull-requests: read strict: false safe-outputs: diff --git a/pkg/workflow/activation_checkout_test.go b/pkg/workflow/activation_checkout_test.go index 5d14804dcf1..6c39050def9 100644 --- a/pkg/workflow/activation_checkout_test.go +++ b/pkg/workflow/activation_checkout_test.go @@ -29,10 +29,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false ---`, description: "Activation job should not include checkout step - uses GitHub API instead", @@ -44,10 +42,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false ---`, description: "Activation job should not include checkout - uses GitHub API instead", @@ -60,10 +56,8 @@ on: types: [opened] reaction: eyes permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false ---`, description: "Activation job with reaction should not include checkout - uses GitHub API instead", diff --git a/pkg/workflow/agentic_output_test.go b/pkg/workflow/agentic_output_test.go index 77df664fcdf..20fa552f9f3 100644 --- a/pkg/workflow/agentic_output_test.go +++ b/pkg/workflow/agentic_output_test.go @@ -23,14 +23,12 @@ func TestAgenticOutputCollection(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -124,14 +122,12 @@ func TestCodexEngineWithOutputSteps(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues] engine: codex -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: diff --git a/pkg/workflow/allow_github_references_env_test.go b/pkg/workflow/allow_github_references_env_test.go index ed0642ce905..dc63dab717f 100644 --- a/pkg/workflow/allow_github_references_env_test.go +++ b/pkg/workflow/allow_github_references_env_test.go @@ -25,12 +25,10 @@ func TestAllowGitHubReferencesEnvVar(t *testing.T) { workflow: `--- on: push engine: copilot -features: - dangerous-permissions-write: true strict: false permissions: contents: read - issues: write + issues: read safe-outputs: allowed-github-references: ["repo"] create-issue: {} @@ -48,12 +46,10 @@ Test workflow with allowed-github-references. workflow: `--- on: push engine: copilot -features: - dangerous-permissions-write: true strict: false permissions: contents: read - issues: write + issues: read safe-outputs: allowed-github-references: ["repo", "org/repo2", "org/repo3"] create-issue: {} @@ -71,12 +67,10 @@ Test workflow with multiple allowed repos. workflow: `--- on: push engine: copilot -features: - dangerous-permissions-write: true strict: false permissions: contents: read - issues: write + issues: read safe-outputs: create-issue: {} --- @@ -92,12 +86,10 @@ Test workflow without allowed-github-references. workflow: `--- on: push engine: copilot -features: - dangerous-permissions-write: true strict: false permissions: contents: read - issues: write + issues: read safe-outputs: allowed-github-references: ["my-org/my-repo", "test-org/test.repo"] create-issue: {} @@ -115,12 +107,10 @@ Test workflow with special characters in repo names. workflow: `--- on: push engine: copilot -features: - dangerous-permissions-write: true strict: false permissions: contents: read - issues: write + issues: read safe-outputs: allowed-github-references: ["repo", "microsoft/vscode"] create-issue: {} @@ -138,12 +128,10 @@ Test workflow mixing repo keyword with specific repos. workflow: `--- on: push engine: copilot -features: - dangerous-permissions-write: true strict: false permissions: contents: read - issues: write + issues: read safe-outputs: allowed-github-references: ["octocat/hello-world", "github/copilot"] create-issue: {} diff --git a/pkg/workflow/aw_info_tmp_test.go b/pkg/workflow/aw_info_tmp_test.go index 04621451549..a26f50da6fe 100644 --- a/pkg/workflow/aw_info_tmp_test.go +++ b/pkg/workflow/aw_info_tmp_test.go @@ -22,14 +22,12 @@ func TestAwInfoTmpPath(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/checkout_optimization_test.go b/pkg/workflow/checkout_optimization_test.go index 93dbdb6f191..809de7cdfd3 100644 --- a/pkg/workflow/checkout_optimization_test.go +++ b/pkg/workflow/checkout_optimization_test.go @@ -43,14 +43,12 @@ on: issues: types: [opened] permissions: - issues: write + issues: read pull-requests: read tools: github: toolsets: [issues, pull_requests] engine: claude -features: - dangerous-permissions-write: true strict: false ---`, expectedHasCheckout: true, @@ -64,14 +62,12 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: toolsets: [repos, issues, pull_requests] engine: claude -features: - dangerous-permissions-write: true strict: false ---`, expectedHasCheckout: true, @@ -85,7 +81,7 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read steps: - name: Custom checkout @@ -98,8 +94,6 @@ tools: github: toolsets: [issues] engine: claude -features: - dangerous-permissions-write: true strict: false ---`, expectedHasCheckout: false, @@ -217,13 +211,13 @@ func TestShouldAddCheckoutStep(t *testing.T) { }, { name: "contents write permission specified, no custom steps", - permissions: "permissions:\n contents: write", + permissions: "permissions:\n contents: read", customSteps: "", expected: true, }, { name: "no contents permission specified, no custom steps - checkout added for .github access", - permissions: "permissions:\n issues: write", + permissions: "permissions:\n issues: read", customSteps: "", expected: true, }, diff --git a/pkg/workflow/checkout_persist_credentials_test.go b/pkg/workflow/checkout_persist_credentials_test.go index 7ab9160f0cc..2bc8338ed43 100644 --- a/pkg/workflow/checkout_persist_credentials_test.go +++ b/pkg/workflow/checkout_persist_credentials_test.go @@ -27,14 +27,12 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false ---`, description: "Main job checkout step should include persist-credentials: false", diff --git a/pkg/workflow/compile_outputs_allowed_labels_test.go b/pkg/workflow/compile_outputs_allowed_labels_test.go index ccde0a8e803..9771f29e3d7 100644 --- a/pkg/workflow/compile_outputs_allowed_labels_test.go +++ b/pkg/workflow/compile_outputs_allowed_labels_test.go @@ -29,10 +29,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -53,7 +51,7 @@ on: types: [opened] permissions: contents: read - discussions: write + discussions: read engine: claude strict: false safe-outputs: @@ -74,11 +72,9 @@ on: issues: types: [opened] permissions: - contents: write - pull-requests: write + contents: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -98,13 +94,11 @@ on: issues: types: [opened] permissions: - contents: write - issues: write - discussions: write - pull-requests: write + contents: read + issues: read + discussions: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -215,12 +209,10 @@ on: issues: types: [opened] permissions: - contents: write - issues: write - pull-requests: write + contents: read + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -283,10 +275,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: diff --git a/pkg/workflow/compile_outputs_comment_test.go b/pkg/workflow/compile_outputs_comment_test.go index 911aa6e26d0..5814589e48c 100644 --- a/pkg/workflow/compile_outputs_comment_test.go +++ b/pkg/workflow/compile_outputs_comment_test.go @@ -22,11 +22,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-comment: @@ -71,11 +69,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-comment: @@ -120,11 +116,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-comment: @@ -174,11 +168,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-comment: @@ -233,14 +225,12 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read tools: github: allowed: [issue_read] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-comment: @@ -282,8 +272,8 @@ This workflow tests the safe_outputs job generation. t.Error("Expected 10-minute timeout in safe_outputs job") } - if !strings.Contains(lockContent, "permissions:\n contents: read\n issues: write\n pull-requests: write") { - t.Error("Expected correct permissions in safe_outputs job") + if !strings.Contains(lockContent, "permissions:\n contents: read\n discussions: write\n issues: write\n pull-requests: write") { + t.Error("Expected correct permissions in safe_outputs job (discussions: write is always included for add-comment)") } // Verify the job uses github-script @@ -331,11 +321,9 @@ func TestOutputCommentJobSkippedForNonIssueEvents(t *testing.T) { on: push permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-comment: diff --git a/pkg/workflow/compile_outputs_issue_test.go b/pkg/workflow/compile_outputs_issue_test.go index 7958b3e40ff..80b86f75a46 100644 --- a/pkg/workflow/compile_outputs_issue_test.go +++ b/pkg/workflow/compile_outputs_issue_test.go @@ -20,11 +20,9 @@ func TestOutputConfigParsing(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -87,11 +85,9 @@ func TestOutputConfigEmpty(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -128,11 +124,9 @@ func TestOutputConfigNull(t *testing.T) { on: push permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -212,14 +206,12 @@ func TestOutputIssueJobGeneration(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -305,11 +297,9 @@ func TestOutputIssueJobGenerationWithCopilotAssigneeAddsAssignmentStep(t *testin on: push permissions: contents: read - issues: write + issues: read pull-requests: read engine: copilot -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: diff --git a/pkg/workflow/compile_outputs_label_test.go b/pkg/workflow/compile_outputs_label_test.go index 4ecc77342c6..3848bb82697 100644 --- a/pkg/workflow/compile_outputs_label_test.go +++ b/pkg/workflow/compile_outputs_label_test.go @@ -24,11 +24,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -86,14 +84,12 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read tools: github: allowed: [issue_read] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -196,11 +192,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -276,11 +270,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -360,11 +352,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -419,11 +409,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -488,11 +476,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -534,14 +520,12 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read tools: github: allowed: [issue_read] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -607,14 +591,12 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read tools: github: allowed: [issue_read] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -673,11 +655,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -718,11 +698,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: {} @@ -763,11 +741,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: add-labels: @@ -853,11 +829,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: remove-labels: diff --git a/pkg/workflow/compile_outputs_pr_test.go b/pkg/workflow/compile_outputs_pr_test.go index 815cbbe1d64..5e939305cd9 100644 --- a/pkg/workflow/compile_outputs_pr_test.go +++ b/pkg/workflow/compile_outputs_pr_test.go @@ -22,11 +22,9 @@ func TestOutputPullRequestConfigParsing(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -89,14 +87,12 @@ func TestOutputPullRequestJobGeneration(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -197,14 +193,12 @@ func TestOutputPullRequestDraftFalse(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -273,14 +267,12 @@ func TestOutputPullRequestDraftTrue(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -353,14 +345,12 @@ on: default: true permissions: contents: read - pull-requests: write + pull-requests: read issues: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -419,11 +409,9 @@ func TestCreatePullRequestIfNoChangesConfig(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -468,11 +456,9 @@ This workflow tests the create-pull-request if-no-changes configuration parsing. on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -609,12 +595,10 @@ on: pull_request: types: [opened] permissions: - contents: write - pull-requests: write + contents: read + pull-requests: read issues: read strict: false -features: - dangerous-permissions-write: true safe-outputs: create-pull-request: title-prefix: "[bot] " @@ -687,10 +671,8 @@ func TestOutputPullRequestFallbackAsIssueFalse(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: @@ -791,10 +773,8 @@ func TestOutputPullRequestFallbackAsIssueDefault(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-pull-request: diff --git a/pkg/workflow/compiler_benchmark_test.go b/pkg/workflow/compiler_benchmark_test.go index 15af6a0bb3f..57aabe6c737 100644 --- a/pkg/workflow/compiler_benchmark_test.go +++ b/pkg/workflow/compiler_benchmark_test.go @@ -24,10 +24,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read, add_issue_comment, list_issues] @@ -68,10 +66,8 @@ on: types: [opened, synchronize] permissions: contents: read - pull-requests: write + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true mcp-servers: github: mode: remote @@ -134,10 +130,8 @@ on: - cron: "0 9 * * 1" permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true imports: - shared/web-tools.md timeout-minutes: 20 @@ -174,10 +168,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read, add_issue_comment] @@ -220,8 +212,8 @@ on: forks: ["org/*", "trusted/repo"] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read actions: read engine: id: copilot @@ -290,10 +282,8 @@ func BenchmarkGenerateYAML(b *testing.B) { on: push permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true tools: github: allowed: [get_repository, list_commits] @@ -345,9 +335,9 @@ on: default: false permissions: contents: read - issues: write - pull-requests: write - deployments: write + issues: read + pull-requests: read + deployments: read engine: id: copilot max-turns: 10 diff --git a/pkg/workflow/compiler_cache_test.go b/pkg/workflow/compiler_cache_test.go index c768d973472..25f7c0cb98a 100644 --- a/pkg/workflow/compiler_cache_test.go +++ b/pkg/workflow/compiler_cache_test.go @@ -337,14 +337,12 @@ on: issues: types: [opened] permissions: - contents: write - issues: write + contents: read + issues: read tools: github: toolsets: [repos, issues] engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -420,8 +418,8 @@ This workflow has custom permissions that should override defaults. // Verify custom permissions are applied expectedCustomPermissions := map[string]string{ - "contents": "write", - "issues": "write", + "contents": "read", + "issues": "read", } for key, expectedValue := range expectedCustomPermissions { diff --git a/pkg/workflow/compiler_compilation_test.go b/pkg/workflow/compiler_compilation_test.go index 621cd908194..43bb73e52d9 100644 --- a/pkg/workflow/compiler_compilation_test.go +++ b/pkg/workflow/compiler_compilation_test.go @@ -24,12 +24,10 @@ on: push timeout-minutes: 10 permissions: contents: read - issues: write + issues: read pull-requests: read engine: copilot strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues, create_issue] @@ -111,13 +109,11 @@ on: issues: types: [opened] permissions: - issues: write + issues: read tools: github: allowed: [create_issue_comment] engine: claude -features: - dangerous-permissions-write: true strict: false ---`, expectError: true, @@ -131,13 +127,11 @@ on: issues: types: [opened] permissions: - issues: write + issues: read tools: github: allowed: [create_issue_comment] engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -154,13 +148,11 @@ on: issues: types: [opened] permissions: - issues: write + issues: read tools: github: allowed: [create_issue_comment] engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -171,7 +163,7 @@ strict: false }, { name: "frontmatter_with_just_newlines", - content: "---\non:\n issues:\n types: [opened]\npermissions:\n issues: write\ntools:\n github:\n allowed: [add_issue_comment]\nengine: claude\n---\n\n\n\n", + content: "---\non:\n issues:\n types: [opened]\npermissions:\n issues: read\ntools:\n github:\n allowed: [add_issue_comment]\nengine: claude\n---\n\n\n\n", expectError: true, expectedErrorMsg: "no markdown content found", description: "Should error when workflow has only frontmatter followed by just newlines", @@ -184,14 +176,12 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [create_issue_comment] engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -211,14 +201,12 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [create_issue_comment] engine: claude -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/compiler_draft_test.go b/pkg/workflow/compiler_draft_test.go index 399894cc5e0..79e6e5a57ac 100644 --- a/pkg/workflow/compiler_draft_test.go +++ b/pkg/workflow/compiler_draft_test.go @@ -35,12 +35,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -58,12 +56,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -80,12 +76,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -104,12 +98,10 @@ if: github.actor != 'dependabot[bot]' permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -129,12 +121,10 @@ if: github.actor != 'dependabot[bot]' permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -151,12 +141,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] diff --git a/pkg/workflow/compiler_expression_size_test.go b/pkg/workflow/compiler_expression_size_test.go index c992a085843..2cd5c305021 100644 --- a/pkg/workflow/compiler_expression_size_test.go +++ b/pkg/workflow/compiler_expression_size_test.go @@ -27,11 +27,9 @@ on: push timeout-minutes: 10 permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues, issue_read] @@ -76,11 +74,9 @@ on: push timeout-minutes: 10 permissions: contents: read - pull-requests: write + pull-requests: read issues: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues] @@ -127,11 +123,9 @@ on: push timeout-minutes: 10 permissions: contents: read - pull-requests: write + pull-requests: read issues: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues] diff --git a/pkg/workflow/compiler_file_size_test.go b/pkg/workflow/compiler_file_size_test.go index 3f9b1990024..62f9630ec63 100644 --- a/pkg/workflow/compiler_file_size_test.go +++ b/pkg/workflow/compiler_file_size_test.go @@ -27,11 +27,9 @@ on: push timeout-minutes: 10 permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues, create_issue] @@ -72,11 +70,9 @@ on: push timeout-minutes: 10 permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues, create_issue] diff --git a/pkg/workflow/compiler_forks_test.go b/pkg/workflow/compiler_forks_test.go index 4f12a794f99..6b06a0d001d 100644 --- a/pkg/workflow/compiler_forks_test.go +++ b/pkg/workflow/compiler_forks_test.go @@ -33,12 +33,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -60,12 +58,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -89,12 +85,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -119,12 +113,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -147,12 +139,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -175,12 +165,10 @@ if: github.actor != 'dependabot[bot]' permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -201,12 +189,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -227,12 +213,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -253,12 +237,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -278,12 +260,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -366,12 +346,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -396,12 +374,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -420,12 +396,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -443,12 +417,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -552,11 +524,9 @@ on: reaction: eyes permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -593,11 +563,9 @@ on: stop-after: +3h permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] diff --git a/pkg/workflow/compiler_jobs_test.go b/pkg/workflow/compiler_jobs_test.go index 2d6b22b21cb..ad431594dc1 100644 --- a/pkg/workflow/compiler_jobs_test.go +++ b/pkg/workflow/compiler_jobs_test.go @@ -1300,7 +1300,7 @@ func TestJobsWithRepoMemoryDependencies(t *testing.T) { Name: "Test Workflow", AI: "copilot", RunsOn: "runs-on: ubuntu-latest", - Permissions: "permissions:\n contents: write", + Permissions: "permissions:\n contents: read", RepoMemoryConfig: &RepoMemoryConfig{ Memories: []RepoMemoryEntry{ { diff --git a/pkg/workflow/compiler_orchestrator_engine_test.go b/pkg/workflow/compiler_orchestrator_engine_test.go index b4a99f94f61..8aac9cfef59 100644 --- a/pkg/workflow/compiler_orchestrator_engine_test.go +++ b/pkg/workflow/compiler_orchestrator_engine_test.go @@ -165,8 +165,6 @@ engine: copilot on: push engine: copilot strict: false -features: - dangerous-permissions-write: true ---`, cliStrict: false, expectStrict: false, diff --git a/pkg/workflow/compiler_orchestrator_test.go b/pkg/workflow/compiler_orchestrator_test.go index d4d39b9df64..1db090d87b7 100644 --- a/pkg/workflow/compiler_orchestrator_test.go +++ b/pkg/workflow/compiler_orchestrator_test.go @@ -21,8 +21,6 @@ on: push engine: copilot timeout-minutes: 10 strict: false -features: - dangerous-permissions-write: true permissions: contents: read --- @@ -348,7 +346,7 @@ func TestParseWorkflowFile_StrictMode(t *testing.T) { if *tt.yamlStrict { frontmatter += "\nstrict: true" } else { - frontmatter += "\nstrict: false\nfeatures:\n dangerous-permissions-write: true" + frontmatter += "\nstrict: false" } } frontmatter += "\n---" diff --git a/pkg/workflow/compiler_orchestrator_workflow.go b/pkg/workflow/compiler_orchestrator_workflow.go index 289e43fb881..b5949e859ae 100644 --- a/pkg/workflow/compiler_orchestrator_workflow.go +++ b/pkg/workflow/compiler_orchestrator_workflow.go @@ -73,6 +73,11 @@ func (c *Compiler) ParseWorkflowFile(markdownPath string) (*WorkflowData, error) return nil, fmt.Errorf("%s: %w", cleanPath, err) } + // Validate GitHub tool read-only configuration + if err := validateGitHubReadOnly(workflowData.ParsedTools, workflowData.Name); err != nil { + return nil, fmt.Errorf("%s: %w", cleanPath, err) + } + // Validate GitHub guard policy configuration if err := validateGitHubGuardPolicy(workflowData.ParsedTools, workflowData.Name); err != nil { return nil, fmt.Errorf("%s: %w", cleanPath, err) diff --git a/pkg/workflow/compiler_orchestrator_workflow_test.go b/pkg/workflow/compiler_orchestrator_workflow_test.go index df53d735ca9..0281b655bc3 100644 --- a/pkg/workflow/compiler_orchestrator_workflow_test.go +++ b/pkg/workflow/compiler_orchestrator_workflow_test.go @@ -1007,15 +1007,13 @@ name: Phase Test Workflow description: Tests phase data flow source: test-source strict: false -features: - dangerous-permissions-write: true tools: bash: ["echo", "ls"] github: allowed: [list_issues] permissions: contents: read - issues: write + issues: read network: allowed: - github.com diff --git a/pkg/workflow/compiler_performance_benchmark_test.go b/pkg/workflow/compiler_performance_benchmark_test.go index 1326d25f03e..0bc1399f02c 100644 --- a/pkg/workflow/compiler_performance_benchmark_test.go +++ b/pkg/workflow/compiler_performance_benchmark_test.go @@ -21,10 +21,8 @@ func BenchmarkCompileSimpleWorkflow(b *testing.B) { on: issues permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true tools: bash: ["echo", "cat"] timeout-minutes: 5 @@ -63,8 +61,8 @@ on: types: [opened, synchronize, reopened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: id: copilot max-turns: 5 @@ -121,10 +119,8 @@ func BenchmarkCompileMCPWorkflow(b *testing.B) { on: pull_request permissions: contents: read - pull-requests: write + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true mcp-servers: github: mode: remote @@ -173,10 +169,8 @@ on: types: [opened, synchronize] permissions: contents: read - pull-requests: write + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true mcp-servers: github: mode: remote @@ -224,10 +218,8 @@ func BenchmarkParseWorkflow(b *testing.B) { on: issues permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true tools: bash: ["echo"] --- @@ -262,10 +254,8 @@ func BenchmarkValidation(b *testing.B) { on: pull_request permissions: contents: read - pull-requests: write + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true mcp-servers: github: mode: remote diff --git a/pkg/workflow/compiler_poststeps_test.go b/pkg/workflow/compiler_poststeps_test.go index ac859dfa8ca..497857836e1 100644 --- a/pkg/workflow/compiler_poststeps_test.go +++ b/pkg/workflow/compiler_poststeps_test.go @@ -23,7 +23,7 @@ func TestPostStepsGeneration(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: @@ -40,8 +40,6 @@ post-steps: name: test-artifact path: test-file.txt engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -116,7 +114,7 @@ func TestPostStepsOnly(t *testing.T) { on: issues permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: @@ -125,8 +123,6 @@ post-steps: - name: Only Post Step run: echo "This runs after AI only" engine: claude -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/compiler_reactions_numeric_test.go b/pkg/workflow/compiler_reactions_numeric_test.go index e71300a8ca6..60976186e62 100644 --- a/pkg/workflow/compiler_reactions_numeric_test.go +++ b/pkg/workflow/compiler_reactions_numeric_test.go @@ -24,7 +24,7 @@ on: reaction: invalid_emoji permissions: contents: read - issues: write + issues: read pull-requests: read strict: false tools: @@ -106,10 +106,8 @@ on: reaction: %s permissions: contents: read - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -151,10 +149,8 @@ on: reaction: 2 permissions: contents: read - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] diff --git a/pkg/workflow/compiler_string_api.go b/pkg/workflow/compiler_string_api.go index 94f65371dc6..d010394da38 100644 --- a/pkg/workflow/compiler_string_api.go +++ b/pkg/workflow/compiler_string_api.go @@ -130,6 +130,11 @@ func (c *Compiler) ParseWorkflowString(content string, virtualPath string) (*Wor return nil, fmt.Errorf("%s: %w", cleanPath, err) } + // Validate GitHub tool read-only configuration + if err := validateGitHubReadOnly(workflowData.ParsedTools, workflowData.Name); err != nil { + return nil, fmt.Errorf("%s: %w", cleanPath, err) + } + // Validate GitHub guard policy configuration if err := validateGitHubGuardPolicy(workflowData.ParsedTools, workflowData.Name); err != nil { return nil, fmt.Errorf("%s: %w", cleanPath, err) diff --git a/pkg/workflow/compiler_template_validation_test.go b/pkg/workflow/compiler_template_validation_test.go index c82742ed18a..a1975c0933d 100644 --- a/pkg/workflow/compiler_template_validation_test.go +++ b/pkg/workflow/compiler_template_validation_test.go @@ -26,10 +26,8 @@ func TestCompilerRejectsIncludesInTemplateRegions(t *testing.T) { content: `--- on: issues permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true --- # Valid Workflow @@ -46,10 +44,8 @@ This is valid. content: `--- on: issues permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true --- # Invalid Workflow @@ -66,7 +62,7 @@ This should fail. content: `--- on: pull_request permissions: - pull-requests: write + pull-requests: read strict: false --- @@ -83,7 +79,7 @@ strict: false content: `--- on: issues permissions: - issues: write + issues: read strict: false --- diff --git a/pkg/workflow/compiler_test.go b/pkg/workflow/compiler_test.go index d8e5e6828b5..91fadec55a2 100644 --- a/pkg/workflow/compiler_test.go +++ b/pkg/workflow/compiler_test.go @@ -29,8 +29,6 @@ permissions: pull-requests: read engine: copilot strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues, create_issue] @@ -320,8 +318,6 @@ func TestCompileWorkflow_LockFileSize(t *testing.T) { on: push engine: copilot strict: false -features: - dangerous-permissions-write: true --- # Size Test Workflow diff --git a/pkg/workflow/compiler_yaml_test.go b/pkg/workflow/compiler_yaml_test.go index 523c6b34c22..f45cb31bce7 100644 --- a/pkg/workflow/compiler_yaml_test.go +++ b/pkg/workflow/compiler_yaml_test.go @@ -30,14 +30,12 @@ func TestCompileWorkflowWithInvalidYAML(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -55,13 +53,11 @@ Invalid YAML with unclosed bracket.`, on: push permissions: contents: read - issues: write + issues: read pull-requests: read invalid: yaml: syntax more: bad engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -79,10 +75,8 @@ Invalid YAML with bad mapping.`, on: push permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -100,14 +94,12 @@ Invalid YAML with bad indentation.`, on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: ["list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -128,10 +120,8 @@ permissions: issues: read pull-requests: read permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -169,11 +159,9 @@ Invalid YAML with non-boolean value for permissions.`, on: push permissions contents: read - issues: write + issues: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -263,8 +251,6 @@ Invalid YAML with malformed nested structure.`, on: push permissions: {contents: read, issues: write engine: claude -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/compute_text_lazy_test.go b/pkg/workflow/compute_text_lazy_test.go index fe80f444aef..ee22047dd55 100644 --- a/pkg/workflow/compute_text_lazy_test.go +++ b/pkg/workflow/compute_text_lazy_test.go @@ -31,10 +31,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [issues] @@ -57,10 +55,8 @@ on: schedule: - cron: "0 9 * * 1" permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [issues] @@ -445,10 +441,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [issues] @@ -469,10 +463,8 @@ on: pull_request: types: [opened] permissions: - pull-requests: write + pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [pull_requests] @@ -493,10 +485,8 @@ on: discussion: types: [created] permissions: - discussions: write + discussions: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [discussions] @@ -517,10 +507,8 @@ on: issue_comment: types: [created] permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [issues] @@ -541,10 +529,8 @@ on: schedule: - cron: "0 9 * * 1" permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [issues] @@ -565,10 +551,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [issues] diff --git a/pkg/workflow/create_pull_request_ci_trigger_token_test.go b/pkg/workflow/create_pull_request_ci_trigger_token_test.go index 86ea8deae3d..336b29fcf6b 100644 --- a/pkg/workflow/create_pull_request_ci_trigger_token_test.go +++ b/pkg/workflow/create_pull_request_ci_trigger_token_test.go @@ -69,14 +69,12 @@ func TestCreatePullRequestCITriggerToken(t *testing.T) { on: push permissions: contents: read - pull-requests: write + pull-requests: read issues: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false ` + safeOutputsConfig + ` --- @@ -168,13 +166,11 @@ on: types: [opened] permissions: contents: read - pull-requests: write + pull-requests: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false ` + safeOutputsConfig + ` --- diff --git a/pkg/workflow/dangerous_permissions_validation.go b/pkg/workflow/dangerous_permissions_validation.go index c38a01f17e1..bf0c69c651b 100644 --- a/pkg/workflow/dangerous_permissions_validation.go +++ b/pkg/workflow/dangerous_permissions_validation.go @@ -4,14 +4,12 @@ import ( "fmt" "strings" - "github.com/github/gh-aw/pkg/constants" "github.com/github/gh-aw/pkg/logger" ) var dangerousPermissionsLog = logger.New("workflow:dangerous_permissions_validation") -// validateDangerousPermissions validates that write permissions are not used unless -// the dangerous-permissions-write feature flag is enabled. +// validateDangerousPermissions validates that write permissions are not used. // // This validation applies to: // - Top-level workflow permissions @@ -20,17 +18,10 @@ var dangerousPermissionsLog = logger.New("workflow:dangerous_permissions_validat // - Custom jobs (jobs defined in the jobs: section) // - Safe outputs jobs (jobs defined in safe-outputs.job section) // -// Returns an error if write permissions are found without the feature flag enabled. +// Returns an error if write permissions are found. func validateDangerousPermissions(workflowData *WorkflowData) error { dangerousPermissionsLog.Print("Starting dangerous permissions validation") - // Check if the feature flag is enabled - featureEnabled := isFeatureEnabled(constants.DangerousPermissionsWriteFeatureFlag, workflowData) - if featureEnabled { - dangerousPermissionsLog.Print("dangerous-permissions-write feature flag is enabled, allowing write permissions") - return nil - } - // Parse the top-level workflow permissions if workflowData.Permissions == "" { dangerousPermissionsLog.Print("No permissions defined, validation passed") @@ -46,7 +37,7 @@ func validateDangerousPermissions(workflowData *WorkflowData) error { // Check for write permissions writePermissions := findWritePermissions(permissions) if len(writePermissions) > 0 { - dangerousPermissionsLog.Printf("Found %d write permissions without feature flag", len(writePermissions)) + dangerousPermissionsLog.Printf("Found %d write permissions", len(writePermissions)) return formatDangerousPermissionsError(writePermissions) } diff --git a/pkg/workflow/dangerous_permissions_validation_test.go b/pkg/workflow/dangerous_permissions_validation_test.go index 2669926387b..b9ac8c95c32 100644 --- a/pkg/workflow/dangerous_permissions_validation_test.go +++ b/pkg/workflow/dangerous_permissions_validation_test.go @@ -27,31 +27,23 @@ func TestValidateDangerousPermissions(t *testing.T) { shouldError: false, }, { - name: "write permission without feature flag - should error", + name: "write permission - should error", permissions: "permissions:\n contents: write", shouldError: true, errorContains: "Write permissions are not allowed", }, { - name: "multiple write permissions without feature flag - should error", + name: "multiple write permissions - should error", permissions: "permissions:\n contents: write\n issues: write", shouldError: true, errorContains: "Write permissions are not allowed", }, { - name: "write permission with feature flag enabled - should pass", + name: "write permission with feature flag is still an error", permissions: "permissions:\n contents: write", features: map[string]any{ "dangerous-permissions-write": true, }, - shouldError: false, - }, - { - name: "write permission with feature flag disabled - should error", - permissions: "permissions:\n contents: write", - features: map[string]any{ - "dangerous-permissions-write": false, - }, shouldError: true, errorContains: "Write permissions are not allowed", }, @@ -61,35 +53,19 @@ func TestValidateDangerousPermissions(t *testing.T) { shouldError: false, }, { - name: "shorthand write-all without feature flag - should error", + name: "shorthand write-all - should error", permissions: "permissions: write-all", shouldError: true, errorContains: "Write permissions are not allowed", }, { - name: "shorthand write-all with feature flag - should pass", - permissions: "permissions: write-all", - features: map[string]any{ - "dangerous-permissions-write": true, - }, - shouldError: false, - }, - { - name: "mixed read and write with feature flag - should pass", - permissions: "permissions:\n contents: read\n issues: write\n pull-requests: read", - features: map[string]any{ - "dangerous-permissions-write": true, - }, - shouldError: false, - }, - { - name: "mixed read and write without feature flag - should error", + name: "mixed read and write - should error", permissions: "permissions:\n contents: read\n issues: write\n pull-requests: read", shouldError: true, errorContains: "issues: write", }, { - name: "id-token write without feature flag - should pass (id-token is safe)", + name: "id-token write - should pass (id-token is safe)", permissions: "permissions:\n id-token: write", shouldError: false, }, diff --git a/pkg/workflow/engine_config_test.go b/pkg/workflow/engine_config_test.go index f99d8850b66..472c0dc928c 100644 --- a/pkg/workflow/engine_config_test.go +++ b/pkg/workflow/engine_config_test.go @@ -272,11 +272,9 @@ func TestCompileWorkflowWithExtendedEngine(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -292,7 +290,7 @@ This is a test workflow.`, on: push permissions: contents: read - issues: write + issues: read pull-requests: read strict: false engine: @@ -313,7 +311,7 @@ This is a test workflow.`, on: push permissions: contents: read - issues: write + issues: read pull-requests: read strict: false engine: diff --git a/pkg/workflow/github_readonly_test.go b/pkg/workflow/github_readonly_test.go index 15187221c9e..65670c2f4ed 100644 --- a/pkg/workflow/github_readonly_test.go +++ b/pkg/workflow/github_readonly_test.go @@ -18,11 +18,11 @@ func TestGetGitHubReadOnly(t *testing.T) { expected: true, }, { - name: "read-only false", + name: "read-only false is ignored (always read-only)", githubTool: map[string]any{ "read-only": false, }, - expected: false, + expected: true, }, { name: "no read-only field", diff --git a/pkg/workflow/github_remote_mode_test.go b/pkg/workflow/github_remote_mode_test.go index 00805e1966b..7d149875d38 100644 --- a/pkg/workflow/github_remote_mode_test.go +++ b/pkg/workflow/github_remote_mode_test.go @@ -32,10 +32,8 @@ func TestGitHubRemoteModeConfiguration(t *testing.T) { frontmatter: `--- on: issues permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false tools: github: @@ -52,10 +50,8 @@ tools: frontmatter: `--- on: issues permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false tools: github: @@ -92,10 +88,8 @@ tools: frontmatter: `--- on: issues permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false tools: github: @@ -111,10 +105,8 @@ tools: frontmatter: `--- on: issues permissions: - issues: write + issues: read engine: copilot -features: - dangerous-permissions-write: true strict: false tools: github: @@ -150,19 +142,16 @@ tools: frontmatter: `--- on: issues permissions: - issues: write + issues: read engine: codex -features: - dangerous-permissions-write: true strict: false tools: github: mode: remote - read-only: false toolsets: [issues] ---`, expectedType: "remote", - expectedURL: "https://api.githubcopilot.com/mcp/", + expectedURL: "https://api.githubcopilot.com/mcp-readonly/", expectedToken: "${{ secrets.GH_AW_GITHUB_MCP_SERVER_TOKEN || secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", engineType: "codex", }, @@ -171,20 +160,17 @@ tools: frontmatter: `--- on: issues permissions: - issues: write + issues: read engine: codex -features: - dangerous-permissions-write: true strict: false tools: github: mode: remote - read-only: false github-token: "${{ secrets.CUSTOM_PAT }}" toolsets: [issues] ---`, expectedType: "remote", - expectedURL: "https://api.githubcopilot.com/mcp/", + expectedURL: "https://api.githubcopilot.com/mcp-readonly/", expectedToken: "${{ secrets.CUSTOM_PAT }}", engineType: "codex", }, diff --git a/pkg/workflow/label_filter_test.go b/pkg/workflow/label_filter_test.go index daaebb37197..a2324001cb8 100644 --- a/pkg/workflow/label_filter_test.go +++ b/pkg/workflow/label_filter_test.go @@ -35,12 +35,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -58,12 +56,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -81,12 +77,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -104,12 +98,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -127,12 +119,10 @@ on: permissions: contents: read - pull-requests: write + pull-requests: read issues: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [get_pull_request] @@ -150,12 +140,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -172,12 +160,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] @@ -243,12 +229,10 @@ on: permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [issue_read] diff --git a/pkg/workflow/local_action_permissions_test.go b/pkg/workflow/local_action_permissions_test.go index 9a84e8b4a55..adeef98bfa8 100644 --- a/pkg/workflow/local_action_permissions_test.go +++ b/pkg/workflow/local_action_permissions_test.go @@ -30,10 +30,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false command: /fix ---`, @@ -48,10 +46,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false ---`, description: "Main agent job should have contents: read when using local actions", @@ -159,10 +155,8 @@ on: issues: types: [opened] permissions: - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false command: /fix ---` diff --git a/pkg/workflow/manual_approval_integration_test.go b/pkg/workflow/manual_approval_integration_test.go index d7b00ed2099..767f4b08e5e 100644 --- a/pkg/workflow/manual_approval_integration_test.go +++ b/pkg/workflow/manual_approval_integration_test.go @@ -56,10 +56,8 @@ on: manual-approval: staging permissions: contents: read - issues: write + issues: read engine: copilot -features: - dangerous-permissions-write: true strict: false ---`, wantEnvironmentInJob: true, diff --git a/pkg/workflow/mcp_github_config.go b/pkg/workflow/mcp_github_config.go index 6e560157199..9c8442d5c7f 100644 --- a/pkg/workflow/mcp_github_config.go +++ b/pkg/workflow/mcp_github_config.go @@ -22,7 +22,7 @@ // - Remote: Uses hosted GitHub MCP service // // Security features: -// - Read-only mode: Prevents write operations (default: true) +// - Read-only mode: Always enforced - write operations via GitHub MCP are not permitted // - GitHub lockdown mode: Restricts access to current repository only // - Automatic lockdown: Enables lockdown for public repositories with GH_AW_GITHUB_TOKEN // - Allowed tools: Restricts available GitHub API operations @@ -56,7 +56,6 @@ // github: // mode: remote # or "local" for Docker // github-token: ${{ secrets.PAT }} -// read-only: true // lockdown: true # or omit for automatic detection // toolsets: [repos, issues, pull_requests] // allowed: [get_repo, list_issues, get_pull_request] @@ -114,17 +113,10 @@ func getGitHubToken(githubTool any) string { return "" } -// getGitHubReadOnly checks if read-only mode is enabled for GitHub tool -// Defaults to true for security -func getGitHubReadOnly(githubTool any) bool { - if toolConfig, ok := githubTool.(map[string]any); ok { - if readOnlySetting, exists := toolConfig["read-only"]; exists { - if boolValue, ok := readOnlySetting.(bool); ok { - return boolValue - } - } - } - return true // default to read-only for security +// getGitHubReadOnly returns true always, since the GitHub MCP server is always read-only. +// Setting read-only: false is not supported and will be flagged as a validation error. +func getGitHubReadOnly(_ any) bool { + return true } // getGitHubLockdown checks if lockdown mode is enabled for GitHub tool diff --git a/pkg/workflow/permissions_import_test.go b/pkg/workflow/permissions_import_test.go index 476f7015c29..da95c4c4302 100644 --- a/pkg/workflow/permissions_import_test.go +++ b/pkg/workflow/permissions_import_test.go @@ -49,7 +49,7 @@ func TestValidateIncludedPermissions(t *testing.T) { }, { name: "Sufficient permissions pass validation", - topPermissionsYAML: "permissions:\n contents: write", + topPermissionsYAML: "permissions:\n contents: read", importedPermissions: `{"contents":"read"}`, expectError: false, }, @@ -62,13 +62,13 @@ func TestValidateIncludedPermissions(t *testing.T) { }, { name: "All required permissions present passes validation", - topPermissionsYAML: "permissions:\n contents: write\n issues: read\n actions: read\n pull-requests: write", - importedPermissions: strings.Join([]string{`{"actions":"read"}`, `{"contents":"write"}`, `{"pull-requests":"write"}`}, "\n"), + topPermissionsYAML: "permissions:\n contents: read\n issues: read\n actions: read\n pull-requests: read", + importedPermissions: strings.Join([]string{`{"actions":"read"}`, `{"contents":"read"}`, `{"pull-requests":"read"}`}, "\n"), expectError: false, }, { name: "Write satisfies read requirement", - topPermissionsYAML: "permissions:\n actions: write", + topPermissionsYAML: "permissions:\n actions: read", importedPermissions: `{"actions":"read"}`, expectError: false, }, @@ -207,16 +207,17 @@ tools: } }) - // Test 3: Insufficient permission level fails validation - t.Run("Insufficient permission level fails validation", func(t *testing.T) { + // Test 3: Missing permission from imported workflow fails validation + t.Run("Missing permission from imported workflow fails validation", func(t *testing.T) { sharedWorkflowUpgradeContent := `--- permissions: - contents: write + contents: read issues: read pull-requests: read + metadata: read --- -# Shared workflow with write permission +# Shared workflow with extra permission ` sharedWorkflowUpgradePath := filepath.Join(sharedDir, "shared-upgrade.md") if err := os.WriteFile(sharedWorkflowUpgradePath, []byte(sharedWorkflowUpgradeContent), 0644); err != nil { @@ -253,8 +254,8 @@ tools: } // Check error message - if !strings.Contains(err.Error(), "Insufficient permissions") { - t.Errorf("Expected error to mention 'Insufficient permissions', got: %v", err) + if !strings.Contains(err.Error(), "permissions") { + t.Errorf("Expected error to mention permissions, got: %v", err) } }) @@ -268,9 +269,7 @@ permissions: contents: read issues: read pull-requests: read - actions: write -features: - dangerous-permissions-write: true + actions: read imports: - shared/shared-permissions.md tools: @@ -307,11 +306,11 @@ func TestExtractPermissionsFromContent(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read --- # Content`, - expected: `{"contents":"read","issues":"write","pull-requests":"read"}`, + expected: `{"contents":"read","issues":"read","pull-requests":"read"}`, wantErr: false, }, { diff --git a/pkg/workflow/permissions_no_github_tool_test.go b/pkg/workflow/permissions_no_github_tool_test.go index 89c8c05d7fe..c9843b40452 100644 --- a/pkg/workflow/permissions_no_github_tool_test.go +++ b/pkg/workflow/permissions_no_github_tool_test.go @@ -48,7 +48,6 @@ permissions: tools: github: toolsets: [repos, issues] - read-only: false --- # Test Workflow @@ -73,11 +72,9 @@ on: push content: `--- on: push permissions: - contents: write - issues: write + contents: read + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [repos, issues] @@ -210,7 +207,6 @@ permissions: tools: github: toolsets: [repos, issues] - read-only: false --- # Test Workflow diff --git a/pkg/workflow/permissions_shortcut_included_test.go b/pkg/workflow/permissions_shortcut_included_test.go index b0decdc6445..d1afa5598c3 100644 --- a/pkg/workflow/permissions_shortcut_included_test.go +++ b/pkg/workflow/permissions_shortcut_included_test.go @@ -30,24 +30,22 @@ func TestPermissionsShortcutInIncludedFiles(t *testing.T) { }, { name: "write-all shortcut in included file", - includedPermissions: "permissions: write-all", - mainPermissions: "permissions: write-all\nfeatures:\n dangerous-permissions-write: true", + includedPermissions: "permissions: read-all", + mainPermissions: "permissions: read-all", expectCompilationError: false, - expectLockFileContains: "permissions: write-all", + expectLockFileContains: "permissions: read-all", }, { name: "object form still works in included file", includedPermissions: `permissions: contents: read - issues: write`, + issues: read`, mainPermissions: `permissions: contents: read - issues: write - pull-requests: read -features: - dangerous-permissions-write: true`, + issues: read + pull-requests: read`, expectCompilationError: false, - expectLockFileContains: "issues: write", + expectLockFileContains: "issues: read", }, } diff --git a/pkg/workflow/permissions_validation.go b/pkg/workflow/permissions_validation.go index ddb059d8ac0..146739a2c2f 100644 --- a/pkg/workflow/permissions_validation.go +++ b/pkg/workflow/permissions_validation.go @@ -104,12 +104,10 @@ func (g *GitHubToolConfig) GetToolsets() string { return expandDefaultToolset(toolsetsStr) } -// IsReadOnly implements ValidatableTool for GitHubToolConfig +// IsReadOnly implements ValidatableTool for GitHubToolConfig. +// The GitHub MCP server always operates in read-only mode. func (g *GitHubToolConfig) IsReadOnly() bool { - if g == nil { - return true // default to read-only for security - } - return g.ReadOnly + return true } // PermissionsValidationResult contains the result of permissions validation diff --git a/pkg/workflow/permissions_validator_test.go b/pkg/workflow/permissions_validator_test.go index b3e5581ec8e..609c7a0a8ab 100644 --- a/pkg/workflow/permissions_validator_test.go +++ b/pkg/workflow/permissions_validator_test.go @@ -342,7 +342,7 @@ func TestValidatePermissions_ComplexScenarios(t *testing.T) { expectMsg []string }{ { - name: "Shorthand read-all with default toolsets", + name: "Shorthand read-all with default toolsets (sufficient in read-only mode)", permissions: NewPermissionsReadAll(), githubToolConfig: &GitHubToolConfig{ Toolset: GitHubToolsets{"default"}, @@ -351,7 +351,7 @@ func TestValidatePermissions_ComplexScenarios(t *testing.T) { expectMsg: []string{}, // read-all satisfies the read-only permission requirements }, { - name: "All: read with discussions toolset", + name: "All: read with discussions toolset (sufficient in read-only mode)", permissions: NewPermissionsAllRead(), githubToolConfig: &GitHubToolConfig{ Toolset: GitHubToolsets{"discussions"}, diff --git a/pkg/workflow/permissions_warning_test.go b/pkg/workflow/permissions_warning_test.go index d1897b72e46..cf36918ce68 100644 --- a/pkg/workflow/permissions_warning_test.go +++ b/pkg/workflow/permissions_warning_test.go @@ -33,7 +33,6 @@ permissions: tools: github: toolsets: [repos, issues] - read-only: false --- # Test Workflow @@ -52,7 +51,6 @@ permissions: tools: github: toolsets: [repos, issues] - read-only: false --- # Test Workflow @@ -67,11 +65,9 @@ tools: content: `--- on: push permissions: - contents: write - issues: write + contents: read + issues: read strict: false -features: - dangerous-permissions-write: true tools: github: toolsets: [repos, issues] @@ -181,7 +177,6 @@ permissions: tools: github: toolsets: [repos, issues, pull_requests] - read-only: false --- # Test Workflow diff --git a/pkg/workflow/pr_checkout_test.go b/pkg/workflow/pr_checkout_test.go index a49fbb4c40a..22ca2c6d498 100644 --- a/pkg/workflow/pr_checkout_test.go +++ b/pkg/workflow/pr_checkout_test.go @@ -31,8 +31,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -53,8 +51,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -77,8 +73,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -99,8 +93,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -121,8 +113,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -143,8 +133,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -160,12 +148,10 @@ on: issue_comment: types: [created] permissions: - issues: write + issues: read contents: read pull-requests: read engine: codex -features: - dangerous-permissions-write: true strict: false --- @@ -264,8 +250,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -337,8 +321,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow diff --git a/pkg/workflow/pr_ready_for_review_checkout_test.go b/pkg/workflow/pr_ready_for_review_checkout_test.go index 2c1f3749646..5d69b4018a8 100644 --- a/pkg/workflow/pr_ready_for_review_checkout_test.go +++ b/pkg/workflow/pr_ready_for_review_checkout_test.go @@ -28,8 +28,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -49,8 +47,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -70,8 +66,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow @@ -86,12 +80,10 @@ on: pull_request: types: [ready_for_review] permissions: - issues: write + issues: read contents: read pull-requests: read engine: codex -features: - dangerous-permissions-write: true strict: false --- @@ -175,8 +167,6 @@ permissions: pull-requests: read engine: claude strict: false -features: - dangerous-permissions-write: true --- # Test Workflow diff --git a/pkg/workflow/processing_benchmark_test.go b/pkg/workflow/processing_benchmark_test.go index cff80cc0359..678bec50bb9 100644 --- a/pkg/workflow/processing_benchmark_test.go +++ b/pkg/workflow/processing_benchmark_test.go @@ -58,11 +58,9 @@ func BenchmarkProcessToolsComplex(b *testing.B) { on: push permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: copilot -features: - dangerous-permissions-write: true strict: false tools: github: @@ -245,14 +243,12 @@ func BenchmarkProcessPermissions(b *testing.B) { on: push permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read actions: read - discussions: write - deployments: write + discussions: read + deployments: read engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -287,10 +283,8 @@ on: roles: [admin, maintainer, write, read] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/reaction_outputs_test.go b/pkg/workflow/reaction_outputs_test.go index 6eead0907e7..19af11f2515 100644 --- a/pkg/workflow/reaction_outputs_test.go +++ b/pkg/workflow/reaction_outputs_test.go @@ -27,8 +27,8 @@ on: status-comment: true permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read strict: false tools: github: @@ -105,8 +105,8 @@ on: status-comment: true permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read strict: false --- diff --git a/pkg/workflow/runtime_import_checkout_test.go b/pkg/workflow/runtime_import_checkout_test.go index 3de3a88dfb6..747c47fdec6 100644 --- a/pkg/workflow/runtime_import_checkout_test.go +++ b/pkg/workflow/runtime_import_checkout_test.go @@ -155,11 +155,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: copilot strict: false -features: - dangerous-permissions-write: true ---`, markdown: "# Agent\n\n{{#runtime-import .github/shared.md}}\n\nDo the task.", expectedHasCheckout: true, @@ -173,11 +171,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: copilot strict: false -features: - dangerous-permissions-write: true ---`, markdown: "# Agent\n\nSimple task instructions here.", expectedHasCheckout: true, @@ -233,11 +229,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: copilot strict: false -features: - dangerous-permissions-write: true ---` markdown := "# Agent\n\n{{#runtime-import .github/shared-instructions.md}}\n\nComplete the task." diff --git a/pkg/workflow/safe_outputs_target_validation_integration_test.go b/pkg/workflow/safe_outputs_target_validation_integration_test.go index 0c1a46018cf..3598c3c6e2f 100644 --- a/pkg/workflow/safe_outputs_target_validation_integration_test.go +++ b/pkg/workflow/safe_outputs_target_validation_integration_test.go @@ -23,10 +23,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -114,10 +112,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -159,11 +155,9 @@ on: types: [opened] permissions: contents: read - issues: write - pull-requests: write + issues: read + pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -234,10 +228,8 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: diff --git a/pkg/workflow/step_summary_test.go b/pkg/workflow/step_summary_test.go index 1c506df0be3..e25842be68f 100644 --- a/pkg/workflow/step_summary_test.go +++ b/pkg/workflow/step_summary_test.go @@ -20,14 +20,12 @@ func TestStepSummaryIncludesProcessedOutput(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read tools: github: allowed: [list_issues] engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: create-issue: @@ -82,11 +80,9 @@ func TestStepSummaryIncludesAgenticRunInfo(t *testing.T) { on: push permissions: contents: read - issues: write + issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true tools: github: allowed: [list_issues] @@ -193,8 +189,6 @@ permissions: issues: read pull-requests: read strict: false -features: - dangerous-permissions-write: true engine: id: claude model: claude-sonnet-4-20250514 diff --git a/pkg/workflow/strict_mode_test.go b/pkg/workflow/strict_mode_test.go index c15db0acc32..81ff8753064 100644 --- a/pkg/workflow/strict_mode_test.go +++ b/pkg/workflow/strict_mode_test.go @@ -116,13 +116,11 @@ permissions: pull-requests: read timeout-minutes: 10 engine: copilot -features: - dangerous-permissions-write: true --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission 'contents: write' is not allowed", + errorMsg: "strict mode: write permission", }, { name: "issues write permission refused in strict mode", @@ -132,13 +130,11 @@ permissions: issues: write timeout-minutes: 10 engine: copilot -features: - dangerous-permissions-write: true --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission 'issues: write' is not allowed", + errorMsg: "strict mode: write permission", }, { name: "pull-requests write permission refused in strict mode", @@ -148,13 +144,11 @@ permissions: pull-requests: write timeout-minutes: 10 engine: copilot -features: - dangerous-permissions-write: true --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission 'pull-requests: write' is not allowed", + errorMsg: "strict mode: write permission", }, { name: "no permissions specified allowed in strict mode", @@ -178,30 +172,26 @@ tools: content: `--- on: push permissions: write-all -features: - dangerous-permissions-write: true timeout-minutes: 10 engine: copilot --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission 'contents: write' is not allowed", + errorMsg: "strict mode: write permission", }, { name: "shorthand write-all permission refused in strict mode", content: `--- on: push permissions: write-all -features: - dangerous-permissions-write: true timeout-minutes: 10 engine: copilot --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission 'contents: write' is not allowed", + errorMsg: "strict mode: write permission", }, { @@ -229,13 +219,11 @@ permissions: pull-requests: read timeout-minutes: 10 engine: copilot -features: - dangerous-permissions-write: true --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission 'contents: write' is not allowed", + errorMsg: "strict mode: write permission", }, } @@ -588,12 +576,10 @@ func TestNonStrictModeAllowsAll(t *testing.T) { content := `--- on: push permissions: - contents: write - issues: write + contents: read + issues: read pull-requests: read engine: copilot -features: - dangerous-permissions-write: true strict: false network: allowed: @@ -647,12 +633,10 @@ network: on: push strict: false permissions: - contents: write + contents: read issues: read pull-requests: read engine: copilot -features: - dangerous-permissions-write: true --- # Test Workflow`, @@ -682,17 +666,18 @@ network: content: `--- on: push permissions: - contents: write + contents: read issues: read pull-requests: read engine: copilot -features: - dangerous-permissions-write: true +network: + allowed: + - "*" --- # Test Workflow`, expectError: true, - errorMsg: "strict mode: write permission", + errorMsg: "strict mode:", }, } @@ -728,12 +713,13 @@ func TestCLIStrictFlagTakesPrecedence(t *testing.T) { on: push strict: false permissions: - contents: write + contents: read issues: read pull-requests: read engine: copilot -features: - dangerous-permissions-write: true +network: + allowed: + - "*" --- # Test Workflow` @@ -749,11 +735,11 @@ features: compiler.SetStrictMode(true) // CLI flag sets strict mode err := compiler.CompileWorkflow(testFile) - // Should fail because CLI flag enforces strict mode and write permission is not allowed + // Should fail because CLI flag enforces strict mode and wildcard network is not allowed if err == nil { t.Error("Expected compilation to fail with CLI --strict flag, but it succeeded") - } else if !strings.Contains(err.Error(), "write permission") { - t.Errorf("Expected write permission error, got: %v", err) + } else if !strings.Contains(err.Error(), "strict mode:") { + t.Errorf("Expected strict mode error, got: %v", err) } } @@ -781,12 +767,10 @@ network: nonStrictWorkflow := `--- on: push permissions: - contents: write + contents: read issues: read pull-requests: read engine: copilot -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/template_expression_integration_test.go b/pkg/workflow/template_expression_integration_test.go index d40bf004317..4d93d4e69db 100644 --- a/pkg/workflow/template_expression_integration_test.go +++ b/pkg/workflow/template_expression_integration_test.go @@ -28,11 +28,9 @@ on: types: [opened, edited] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false --- diff --git a/pkg/workflow/tools_validation.go b/pkg/workflow/tools_validation.go index 49ea7ad3d23..32a8c400e76 100644 --- a/pkg/workflow/tools_validation.go +++ b/pkg/workflow/tools_validation.go @@ -71,6 +71,21 @@ func isGitToolAllowed(tools *Tools) bool { return false } +// validateGitHubReadOnly validates that read-only: false is not set for the GitHub tool. +// The GitHub MCP server always operates in read-only mode; write access is not permitted. +func validateGitHubReadOnly(tools *Tools, workflowName string) error { + if tools == nil || tools.GitHub == nil { + return nil + } + + if !tools.GitHub.ReadOnly { + toolsValidationLog.Printf("Invalid read-only configuration in workflow: %s", workflowName) + return errors.New("invalid GitHub tool configuration: 'tools.github.read-only: false' is not allowed. The GitHub MCP server always operates in read-only mode. Remove the 'read-only' field or set it to 'true'") + } + + return nil +} + // validateGitHubToolConfig validates that the GitHub tool configuration does not // specify both app and github-token at the same time, as only one authentication // method is allowed. diff --git a/pkg/workflow/update_discussion_test.go b/pkg/workflow/update_discussion_test.go index 123808bbf42..7b73d542969 100644 --- a/pkg/workflow/update_discussion_test.go +++ b/pkg/workflow/update_discussion_test.go @@ -21,7 +21,7 @@ on: types: [created] permissions: contents: read - discussions: write + discussions: read engine: claude strict: false safe-outputs: @@ -92,7 +92,7 @@ on: types: [created] permissions: contents: read - discussions: write + discussions: read engine: claude strict: false safe-outputs: @@ -177,7 +177,7 @@ on: types: [created] permissions: contents: read - discussions: write + discussions: read engine: claude strict: false safe-outputs: @@ -233,7 +233,7 @@ on: types: [created] permissions: contents: read - discussions: write + discussions: read engine: claude strict: false safe-outputs: @@ -297,7 +297,7 @@ on: types: [created] permissions: contents: read - discussions: write + discussions: read engine: claude strict: false safe-outputs: diff --git a/pkg/workflow/update_issue_test.go b/pkg/workflow/update_issue_test.go index c01f3832e59..1fcdf64d861 100644 --- a/pkg/workflow/update_issue_test.go +++ b/pkg/workflow/update_issue_test.go @@ -21,11 +21,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -91,11 +89,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -171,11 +167,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -229,11 +223,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -279,11 +271,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -329,11 +319,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: @@ -381,11 +369,9 @@ on: types: [opened] permissions: contents: read - issues: write + issues: read pull-requests: read engine: claude -features: - dangerous-permissions-write: true strict: false safe-outputs: update-issue: diff --git a/pkg/workflow/xml_comments_test.go b/pkg/workflow/xml_comments_test.go index 82278522496..ea182175df7 100644 --- a/pkg/workflow/xml_comments_test.go +++ b/pkg/workflow/xml_comments_test.go @@ -302,13 +302,11 @@ on: issues: types: [opened] permissions: - issues: write + issues: read tools: github: toolsets: [issues] engine: claude -features: - dangerous-permissions-write: true strict: false --- @@ -332,9 +330,7 @@ This is a normal-sized workflow that should compile successfully.` " issues:\n" + " types: [opened]\n" + "permissions:\n" + - " issues: write\n" + - "features:\n" + - " dangerous-permissions-write: true\n" + + " issues: read\n" + "strict: false\n" + "tools:\n" + " github:\n" +