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",