From 056cd03fe2d72ac24d466912823f2b98ed3abfe1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 03:58:41 +0000 Subject: [PATCH 1/2] Initial plan From 0d569c49dc26f944af2c6d2759fc49280ceba157 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 1 Mar 2026 04:17:25 +0000 Subject: [PATCH 2/2] Remove automatic contents:read from agent job permissions in release mode" Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/compiler_activation_jobs.go | 27 ++++++++++--------- .../permissions_explicit_empty_test.go | 4 +-- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/pkg/workflow/compiler_activation_jobs.go b/pkg/workflow/compiler_activation_jobs.go index b9233020243..65c9edba1f6 100644 --- a/pkg/workflow/compiler_activation_jobs.go +++ b/pkg/workflow/compiler_activation_jobs.go @@ -954,21 +954,21 @@ func (c *Compiler) buildMainJob(data *WorkflowData, activationJobCreated bool) ( agentConcurrency := GenerateJobConcurrencyConfig(data) // Set up permissions for the agent job - // Agent job ALWAYS needs contents: read to access .github and .actions folders + // In dev/script mode, automatically add contents: read if the actions folder checkout is needed + // In release mode, use the permissions as specified by the user (no automatic augmentation) permissions := data.Permissions - if permissions == "" { - // No permissions specified, just add contents: read - perms := NewPermissionsContentsRead() - permissions = perms.RenderToYAML() - } else { - // Parse existing permissions and add contents: read - parser := NewPermissionsParser(permissions) - perms := parser.ToPermissions() - - // Only add contents: read if not already present - if level, exists := perms.Get(PermissionContents); !exists || level == PermissionNone { - perms.Set(PermissionContents, PermissionRead) + needsContentsRead := (c.actionMode.IsDev() || c.actionMode.IsScript()) && len(c.generateCheckoutActionsFolder(data)) > 0 + if needsContentsRead { + if permissions == "" { + perms := NewPermissionsContentsRead() permissions = perms.RenderToYAML() + } else { + parser := NewPermissionsParser(permissions) + perms := parser.ToPermissions() + if level, exists := perms.Get(PermissionContents); !exists || level == PermissionNone { + perms.Set(PermissionContents, PermissionRead) + permissions = perms.RenderToYAML() + } } } @@ -1032,6 +1032,7 @@ func (c *Compiler) generateCheckoutGitHubFolderForActivation(data *WorkflowData) // the activation job ALWAYS gets contents:read added to its permissions (see buildActivationJob // around line 720). The workflow's original permissions may not include contents:read, // but the activation job will always have it for GitHub API access and runtime imports. + // The agent job uses only the user-specified permissions (no automatic contents:read augmentation). // For activation job, always add sparse checkout of .github and .agents folders // This is needed for runtime imports during prompt generation diff --git a/pkg/workflow/permissions_explicit_empty_test.go b/pkg/workflow/permissions_explicit_empty_test.go index a8e0e2dea5e..ff8ec183415 100644 --- a/pkg/workflow/permissions_explicit_empty_test.go +++ b/pkg/workflow/permissions_explicit_empty_test.go @@ -46,9 +46,9 @@ permissions: {} # Test workflow Test content`, actionMode: ActionModeRelease, - expectedAgentPerms: "permissions:\n contents: read", // Agent job always gets contents: read + expectedAgentPerms: "permissions: {}", // Release mode does NOT add contents: read automatically expectedTopLevelPerms: "permissions: {}", - description: "Release mode with explicit empty permissions should add contents: read to agent job", + description: "Release mode with explicit empty permissions should NOT add contents: read to agent job", }, { name: "no permissions specified in dev mode",