From 74e71349353ed7652059d02629544ad7745ba47e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 10:40:06 +0000 Subject: [PATCH 1/3] Initial plan From 273fe8d68ae0d2217f162006734d1aed37b1099d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 10:55:22 +0000 Subject: [PATCH 2/3] fix: skip GitHub App-only scopes in collectRequiredPermissions to fix dependabot toolset compilation The compiler was incorrectly requiring `vulnerability-alerts: read` as a workflow-level permission when using the `dependabot` toolset (directly or via `toolsets: all`). This is a GitHub App-only scope that cannot be set at the GITHUB_TOKEN/workflow level. Fix: Filter out GitHub App-only permission scopes in `collectRequiredPermissions` so they are not included in the workflow-level permission requirements. This unblocks 6 affected workflows that were failing to compile: - daily-firewall-report.md - deep-report.md - dependabot-go-checker.md - github-mcp-structural-analysis.md - github-mcp-tools-report.md - security-review.md Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw/sessions/44690a38-5e56-4478-8a68-6d8bf5a9b386 --- pkg/workflow/permissions_toolset_data.go | 6 ++++++ pkg/workflow/permissions_validator_test.go | 5 ++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/pkg/workflow/permissions_toolset_data.go b/pkg/workflow/permissions_toolset_data.go index 80538014fa..60bf7534f7 100644 --- a/pkg/workflow/permissions_toolset_data.go +++ b/pkg/workflow/permissions_toolset_data.go @@ -109,6 +109,12 @@ func collectRequiredPermissions(toolsets []string, readOnly bool) map[Permission // Add read permissions only (write tools are not considered for permission requirements) for _, scope := range perms.ReadPermissions { + // Skip GitHub App-only permission scopes; these cannot be set via GITHUB_TOKEN + // and are validated separately in validateGitHubAppOnlyPermissions. + if IsGitHubAppOnlyScope(scope) { + permissionsValidationLog.Printf("Skipping GitHub App-only scope %s for toolset %s", scope, toolset) + continue + } // Always require at least read access if existing, found := required[scope]; !found || existing == PermissionNone { required[scope] = PermissionRead diff --git a/pkg/workflow/permissions_validator_test.go b/pkg/workflow/permissions_validator_test.go index b871783e32..a4da6b7b03 100644 --- a/pkg/workflow/permissions_validator_test.go +++ b/pkg/workflow/permissions_validator_test.go @@ -89,12 +89,11 @@ func TestCollectRequiredPermissions(t *testing.T) { }, }, { - name: "Dependabot toolset requires vulnerability-alerts and security-events", + name: "Dependabot toolset requires only security-events (vulnerability-alerts is GitHub App-only)", toolsets: []string{"dependabot"}, readOnly: false, expected: map[PermissionScope]PermissionLevel{ - PermissionSecurityEvents: PermissionRead, - PermissionVulnerabilityAlerts: PermissionRead, + PermissionSecurityEvents: PermissionRead, }, }, { From ba23156dd87b434d3720468c0f9525c3a9d20968 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Mar 2026 11:11:49 +0000 Subject: [PATCH 3/3] fix: exclude dependabot from 'all' toolset expansion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dependabot toolset requires GitHub App-only permissions (vulnerability-alerts) that cannot be granted via GITHUB_TOKEN. Workflows using `toolsets: all` should not inadvertently pull in the dependabot toolset — users must opt in explicitly with `toolsets: [default, dependabot]` and configure a GitHub App. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> Agent-Logs-Url: https://github.com/github/gh-aw/sessions/d7e286c6-e1be-40da-852c-7a616d322b7c --- pkg/workflow/github_tool_to_toolset_test.go | 9 +++++++- pkg/workflow/github_toolsets.go | 17 ++++++++++++-- pkg/workflow/github_toolsets_test.go | 25 +++++++++++++++------ 3 files changed, 41 insertions(+), 10 deletions(-) diff --git a/pkg/workflow/github_tool_to_toolset_test.go b/pkg/workflow/github_tool_to_toolset_test.go index 8815d1082d..47b2dd969c 100644 --- a/pkg/workflow/github_tool_to_toolset_test.go +++ b/pkg/workflow/github_tool_to_toolset_test.go @@ -291,8 +291,15 @@ func expandToolsetsForTesting(toolsets []string) []string { } } case "all": - // Add all toolsets from the permissions map + // Add all toolsets from the permissions map, excluding those in GitHubToolsetsExcludedFromAll + excludedMap := make(map[string]bool, len(GitHubToolsetsExcludedFromAll)) + for _, ex := range GitHubToolsetsExcludedFromAll { + excludedMap[ex] = true + } for t := range toolsetPermissionsMap { + if excludedMap[t] { + continue + } if !seenToolsets[t] { expanded = append(expanded, t) seenToolsets[t] = true diff --git a/pkg/workflow/github_toolsets.go b/pkg/workflow/github_toolsets.go index fad70f13e3..cc916b4fef 100644 --- a/pkg/workflow/github_toolsets.go +++ b/pkg/workflow/github_toolsets.go @@ -18,6 +18,11 @@ var DefaultGitHubToolsets = []string{"context", "repos", "issues", "pull_request // Use this when the workflow will run in GitHub Actions with GITHUB_TOKEN. var ActionFriendlyGitHubToolsets = []string{"context", "repos", "issues", "pull_requests"} +// GitHubToolsetsExcludedFromAll defines toolsets that are NOT included when "all" is specified. +// These toolsets require GitHub App-only permissions (e.g., vulnerability-alerts) that +// cannot be granted via GITHUB_TOKEN, so they must be opted-in to explicitly. +var GitHubToolsetsExcludedFromAll = []string{"dependabot"} + // ParseGitHubToolsets parses the toolsets string and expands "default" and "all" // into their constituent toolsets. It handles comma-separated lists and deduplicates. func ParseGitHubToolsets(toolsetsStr string) []string { @@ -58,9 +63,17 @@ func ParseGitHubToolsets(toolsetsStr string) []string { } } case "all": - // Add all toolsets from the toolset permissions map - toolsetsLog.Printf("Expanding 'all' to %d toolsets from permissions map", len(toolsetPermissionsMap)) + // Add all toolsets from the toolset permissions map, excluding those that + // require GitHub App-only permissions (see GitHubToolsetsExcludedFromAll). + toolsetsLog.Printf("Expanding 'all' to toolsets from permissions map (excluding %v)", GitHubToolsetsExcludedFromAll) + excludedMap := make(map[string]bool, len(GitHubToolsetsExcludedFromAll)) + for _, ex := range GitHubToolsetsExcludedFromAll { + excludedMap[ex] = true + } for t := range toolsetPermissionsMap { + if excludedMap[t] { + continue + } if !seenToolsets[t] { expanded = append(expanded, t) seenToolsets[t] = true diff --git a/pkg/workflow/github_toolsets_test.go b/pkg/workflow/github_toolsets_test.go index fe4b5996e4..8fdb9ca433 100644 --- a/pkg/workflow/github_toolsets_test.go +++ b/pkg/workflow/github_toolsets_test.go @@ -70,9 +70,9 @@ func TestParseGitHubToolsets(t *testing.T) { expected: []string{"context", "repos", "issues", "pull_requests", "discussions"}, }, { - name: "All expands to all toolsets", + name: "All expands to all toolsets except excluded ones", input: "all", - // Should include all 19 toolsets - we'll check the count + // Should include all toolsets except those in GitHubToolsetsExcludedFromAll (e.g., dependabot) expected: nil, }, { @@ -111,10 +111,21 @@ func TestParseGitHubToolsets(t *testing.T) { t.Run(tt.name, func(t *testing.T) { result := ParseGitHubToolsets(tt.input) - if tt.name == "All expands to all toolsets" { - // Check that all toolsets are present - if len(result) != len(toolsetPermissionsMap) { - t.Errorf("Expected %d toolsets for 'all', got %d", len(toolsetPermissionsMap), len(result)) + if tt.name == "All expands to all toolsets except excluded ones" { + // Check that result is all toolsets minus excluded ones + expectedCount := len(toolsetPermissionsMap) - len(GitHubToolsetsExcludedFromAll) + if len(result) != expectedCount { + t.Errorf("Expected %d toolsets for 'all', got %d: %v", expectedCount, len(result), result) + } + // Verify excluded toolsets are not present + resultMap := make(map[string]bool) + for _, ts := range result { + resultMap[ts] = true + } + for _, ex := range GitHubToolsetsExcludedFromAll { + if resultMap[ex] { + t.Errorf("Excluded toolset %q should not be present in 'all' expansion", ex) + } } return } @@ -175,7 +186,7 @@ func TestParseGitHubToolsetsDeduplication(t *testing.T) { { name: "All with duplicates", input: "all,repos,issues", - expected: len(toolsetPermissionsMap), // All toolsets, duplicates ignored + expected: len(toolsetPermissionsMap) - len(GitHubToolsetsExcludedFromAll), // All toolsets minus excluded, duplicates ignored }, }