From 272960c5674506b3a269ff8dac678f9810c24319 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 15:55:16 +0000 Subject: [PATCH 1/9] Initial plan From 753cf2099b23f33a5a76c3610be80f93bd76173c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:09:09 +0000 Subject: [PATCH 2/9] fix safe_outputs checkout token isolation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/checkout_manager_test.go | 20 ++++++++-------- pkg/workflow/checkout_step_generator.go | 24 ++----------------- .../compiler_safe_outputs_steps_test.go | 19 +++++++++++++++ 3 files changed, 31 insertions(+), 32 deletions(-) diff --git a/pkg/workflow/checkout_manager_test.go b/pkg/workflow/checkout_manager_test.go index 4ca1970d228..8047f69063f 100644 --- a/pkg/workflow/checkout_manager_test.go +++ b/pkg/workflow/checkout_manager_test.go @@ -234,22 +234,22 @@ func TestGenerateDefaultCheckoutStep(t *testing.T) { }) } -// TestCheckoutPushTokenFallback verifies the safe_outputs push-token fallback that -// persists the resolved PR push token into the checkout when keepCredentialsForPush is -// enabled and no explicit checkout token (or app auth) already governs the checkout. -func TestCheckoutPushTokenFallback(t *testing.T) { +// TestCheckoutPushTokenIsolation verifies that the safe_outputs push token is NOT +// injected into checkout steps. Checkout auth must come only from checkout config +// (github-token/github-app) or the default GitHub token for the workflow repository. +func TestCheckoutPushTokenIsolation(t *testing.T) { getPin := func(action string) string { return action + "@v4" } const pushToken = "${{ secrets.PUSH_TOKEN }}" - t.Run("default checkout with no explicit token emits pushToken once", func(t *testing.T) { + t.Run("default checkout with no explicit token does not emit pushToken", func(t *testing.T) { cm := NewCheckoutManager(nil) cm.SetKeepCredentialsForPush(true) cm.SetPushToken(pushToken) lines := cm.GenerateDefaultCheckoutStep(false, "", getPin) combined := strings.Join(lines, "") assert.Contains(t, combined, "persist-credentials: true", "keepCredentialsForPush should retain credentials") - assert.Contains(t, combined, "token: "+pushToken, "should persist the push token") - assert.Equal(t, 1, strings.Count(combined, "token: "), "token must be emitted exactly once") + assert.NotContains(t, combined, "token: "+pushToken, "push token must not be used for checkout") + assert.Equal(t, 0, strings.Count(combined, "token: "), "default checkout should not emit a token line") }) t.Run("default checkout with explicit token does not override with pushToken", func(t *testing.T) { @@ -286,7 +286,7 @@ func TestCheckoutPushTokenFallback(t *testing.T) { assert.NotContains(t, combined, pushToken, "pushToken must not be persisted when credentials are not retained") }) - t.Run("additional checkout with no token uses pushToken", func(t *testing.T) { + t.Run("additional checkout with no token does not use pushToken", func(t *testing.T) { cm := NewCheckoutManager([]*CheckoutConfig{ {Repository: "owner/libs", Path: "./libs"}, }) @@ -295,8 +295,8 @@ func TestCheckoutPushTokenFallback(t *testing.T) { lines := cm.GenerateAdditionalCheckoutSteps(getPin) combined := strings.Join(lines, "") assert.Contains(t, combined, "persist-credentials: true", "keepCredentialsForPush should retain credentials") - assert.Contains(t, combined, "token: "+pushToken, "additional checkout should fall back to the push token") - assert.Equal(t, 1, strings.Count(combined, "token: "), "token must be emitted exactly once") + assert.NotContains(t, combined, "token: "+pushToken, "additional checkout must not fall back to the push token") + assert.Equal(t, 0, strings.Count(combined, "token: "), "additional checkout with no token should not emit a token line") }) t.Run("additional checkout with explicit token does not override with pushToken", func(t *testing.T) { diff --git a/pkg/workflow/checkout_step_generator.go b/pkg/workflow/checkout_step_generator.go index e3af1e11ca8..ae158b0df2b 100644 --- a/pkg/workflow/checkout_step_generator.go +++ b/pkg/workflow/checkout_step_generator.go @@ -82,7 +82,7 @@ func (cm *CheckoutManager) GenerateAdditionalCheckoutSteps(getActionPin func(str if entry.key.path == "" && entry.key.repository == "" { continue } - lines = append(lines, generateCheckoutStepLines(entry, checkoutIndex, cm.keepCredentialsForPush, cm.pushToken, getActionPin)...) + lines = append(lines, generateCheckoutStepLines(entry, checkoutIndex, cm.keepCredentialsForPush, getActionPin)...) } checkoutManagerLog.Printf("Generated %d additional checkout step(s)", len(lines)) return lines @@ -381,10 +381,6 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( sb.WriteString(" persist-credentials: false\n") } - // Track whether a token has been written to the checkout step so the safe_outputs - // push-token fallback below does not double-emit. - tokenEmitted := false - // Apply trial mode overrides if trialMode { if trialLogicalRepoSlug != "" { @@ -392,7 +388,6 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( } effectiveToken := getEffectiveGitHubToken("") fmt.Fprintf(&sb, " token: %s\n", effectiveToken) - tokenEmitted = true } // Apply user overrides (only when NOT in trial mode to avoid conflicts) @@ -433,7 +428,6 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( } if effectiveOverrideToken != "" { fmt.Fprintf(&sb, " token: %s\n", effectiveOverrideToken) - tokenEmitted = true } if override.fetchDepth != nil { fmt.Fprintf(&sb, " fetch-depth: %d\n", *override.fetchDepth) @@ -452,14 +446,6 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( } } - // safe_outputs job: when no explicit token was written above, persist the resolved - // push token so the credential retained in .git/config matches the token the - // safe-output handlers use to fetch/push (avoiding both a wrong-token push and the - // duplicate Authorization header that a separate per-command extraheader would add). - if !trialMode && !tokenEmitted && cm.keepCredentialsForPush && cm.pushToken != "" { - fmt.Fprintf(&sb, " token: %s\n", cm.pushToken) - } - steps := []string{sb.String()} if override != nil && len(override.sparsePatterns) > 0 { steps = append(steps, generateSparseCheckoutPartialCloneResetStep("")) @@ -490,7 +476,7 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( // When keepCredentialsForPush is true (safe_outputs job), credentials are retained // (persist-credentials: true) and the post-checkout cleanup step is suppressed so a later // git fetch/push can authenticate. -func generateCheckoutStepLines(entry *resolvedCheckout, index int, keepCredentialsForPush bool, pushToken string, getActionPin func(string) string) []string { +func generateCheckoutStepLines(entry *resolvedCheckout, index int, keepCredentialsForPush bool, getActionPin func(string) string) []string { checkoutManagerLog.Printf("Generating checkout step lines: index=%d, repo=%q, path=%q, ref=%q, appAuth=%v", index, entry.key.repository, entry.key.path, entry.ref, entry.githubApp != nil) name := "Checkout " + checkoutStepName(entry.key) @@ -523,12 +509,6 @@ func generateCheckoutStepLines(entry *resolvedCheckout, index int, keepCredentia } // Determine effective token: github-app-minted token takes precedence effectiveToken := resolveCheckoutTokenExpression(entry, index, false) - // safe_outputs job: when this checkout declares no token/app of its own, persist the - // resolved push token so the retained .git/config credential matches the token the - // safe-output handlers use to fetch/push. - if effectiveToken == "" && keepCredentialsForPush && pushToken != "" { - effectiveToken = pushToken - } if effectiveToken != "" { fmt.Fprintf(&sb, " token: %s\n", effectiveToken) } diff --git a/pkg/workflow/compiler_safe_outputs_steps_test.go b/pkg/workflow/compiler_safe_outputs_steps_test.go index 9ccdfa4f8e8..4462e4183ec 100644 --- a/pkg/workflow/compiler_safe_outputs_steps_test.go +++ b/pkg/workflow/compiler_safe_outputs_steps_test.go @@ -109,6 +109,25 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { checkContains: []string{ "GIT_TOKEN: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", }, + checkNotContains: []string{ + "token: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + }, + }, + { + name: "safe-outputs github-app token is not used by checkout step", + safeOutputs: &SafeOutputsConfig{ + GitHubApp: &GitHubAppConfig{ + AppID: "${{ vars.APP_ID }}", + PrivateKey: "${{ secrets.APP_PRIVATE_KEY }}", + }, + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + checkContains: []string{ + "GIT_TOKEN: ${{ steps.safe-outputs-app-token.outputs.token }}", + }, + checkNotContains: []string{ + "token: ${{ steps.safe-outputs-app-token.outputs.token }}", + }, }, { name: "push-to-pull-request-branch per-config token flows into git credentials", From c1f5617b5c564f0fdfadf1e4263631c7bba9978d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 16:16:46 +0000 Subject: [PATCH 3/9] test safe_outputs checkout token isolation regressions Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/checkout_step_generator.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pkg/workflow/checkout_step_generator.go b/pkg/workflow/checkout_step_generator.go index ae158b0df2b..f264a217547 100644 --- a/pkg/workflow/checkout_step_generator.go +++ b/pkg/workflow/checkout_step_generator.go @@ -390,7 +390,11 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( fmt.Fprintf(&sb, " token: %s\n", effectiveToken) } - // Apply user overrides (only when NOT in trial mode to avoid conflicts) + // Apply user overrides only when NOT in trial mode to avoid conflicting + // repository/token values in the same checkout step. Note that safe_outputs push + // auth is intentionally isolated from checkout auth: this step only emits tokens + // from checkout config (or trial mode), while push auth is applied later by + // CheckoutManager.GenerateConfigureGitCredentialsSteps. if !trialMode && override != nil { if override.key.wiki { // Wiki checkout: use "{repository}.wiki" as the effective repository. @@ -475,7 +479,8 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( // reference the correct app token minting step when app authentication is configured. // When keepCredentialsForPush is true (safe_outputs job), credentials are retained // (persist-credentials: true) and the post-checkout cleanup step is suppressed so a later -// git fetch/push can authenticate. +// git fetch/push can authenticate after CheckoutManager.GenerateConfigureGitCredentialsSteps +// rewrites remotes with the resolved push token. func generateCheckoutStepLines(entry *resolvedCheckout, index int, keepCredentialsForPush bool, getActionPin func(string) string) []string { checkoutManagerLog.Printf("Generating checkout step lines: index=%d, repo=%q, path=%q, ref=%q, appAuth=%v", index, entry.key.repository, entry.key.path, entry.ref, entry.githubApp != nil) From e641ae8ee13fba263ff65cf7617232c255303273 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 20:45:28 +0000 Subject: [PATCH 4/9] plan: review safe_outputs token isolation for trial mode and side repos Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .github/workflows/avenger.lock.yml | 1 - .github/workflows/changeset.lock.yml | 1 - .github/workflows/chaos-pr-bundle-fuzzer.lock.yml | 1 - .github/workflows/ci-coach.lock.yml | 1 - .github/workflows/cloclo.lock.yml | 1 - .github/workflows/code-scanning-fixer.lock.yml | 1 - .github/workflows/code-simplifier.lock.yml | 1 - .github/workflows/craft.lock.yml | 1 - .github/workflows/daily-agent-of-the-day-blog-writer.lock.yml | 1 - .github/workflows/daily-architecture-diagram.lock.yml | 1 - .../workflows/daily-astrostylelite-markdown-spellcheck.lock.yml | 1 - .github/workflows/daily-caveman-optimizer.lock.yml | 1 - .github/workflows/daily-community-attribution.lock.yml | 1 - .github/workflows/daily-compiler-threat-spec-optimizer.lock.yml | 1 - .github/workflows/daily-doc-healer.lock.yml | 1 - .github/workflows/daily-doc-updater.lock.yml | 1 - .github/workflows/daily-rendering-scripts-verifier.lock.yml | 1 - .github/workflows/daily-safe-output-integrator.lock.yml | 1 - .github/workflows/daily-safeoutputs-git-simulator.lock.yml | 1 - .github/workflows/daily-workflow-updater.lock.yml | 1 - .github/workflows/daily-yamllint-fixer.lock.yml | 1 - .github/workflows/dead-code-remover.lock.yml | 1 - .github/workflows/dependabot-burner.lock.yml | 1 - .github/workflows/dependabot-repair.lock.yml | 1 - .github/workflows/design-decision-gate.lock.yml | 1 - .github/workflows/developer-docs-consolidator.lock.yml | 1 - .github/workflows/dictation-prompt.lock.yml | 1 - .github/workflows/eslint-miner.lock.yml | 1 - .github/workflows/functional-pragmatist.lock.yml | 1 - .github/workflows/github-mcp-tools-report.lock.yml | 1 - .github/workflows/glossary-maintainer.lock.yml | 1 - .github/workflows/go-logger.lock.yml | 1 - .github/workflows/hourly-ci-cleaner.lock.yml | 1 - .github/workflows/instructions-janitor.lock.yml | 1 - .github/workflows/jsweep.lock.yml | 1 - .github/workflows/layout-spec-maintainer.lock.yml | 1 - .github/workflows/linter-miner.lock.yml | 1 - .github/workflows/mergefest.lock.yml | 1 - .github/workflows/necromancer.lock.yml | 1 - .github/workflows/pr-sous-chef.lock.yml | 1 - .github/workflows/q.lock.yml | 1 - .github/workflows/refiner.lock.yml | 1 - .github/workflows/ruflo-backed-task.lock.yml | 1 - .github/workflows/schema-feature-coverage.lock.yml | 1 - .github/workflows/slide-deck-maintainer.lock.yml | 1 - .github/workflows/smoke-create-cross-repo-pr.lock.yml | 1 - .github/workflows/smoke-multi-pr.lock.yml | 1 - .github/workflows/smoke-project.lock.yml | 1 - .github/workflows/smoke-update-cross-repo-pr.lock.yml | 1 - .github/workflows/spec-enforcer.lock.yml | 1 - .github/workflows/spec-extractor.lock.yml | 1 - .github/workflows/technical-doc-writer.lock.yml | 1 - .github/workflows/test-create-pr-error-handling.lock.yml | 1 - .github/workflows/tidy.lock.yml | 1 - .github/workflows/ubuntu-image-analyzer.lock.yml | 1 - .github/workflows/unbloat-docs.lock.yml | 1 - .github/workflows/update-astro.lock.yml | 1 - .github/workflows/weekly-blog-post-writer.lock.yml | 1 - .github/workflows/weekly-editors-health-check.lock.yml | 1 - .github/workflows/weekly-safe-outputs-spec-review.lock.yml | 1 - 60 files changed, 60 deletions(-) diff --git a/.github/workflows/avenger.lock.yml b/.github/workflows/avenger.lock.yml index a8cc455da47..49afff1d4e4 100644 --- a/.github/workflows/avenger.lock.yml +++ b/.github/workflows/avenger.lock.yml @@ -1760,7 +1760,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/changeset.lock.yml b/.github/workflows/changeset.lock.yml index b6f3e74018f..adbb5048cb5 100644 --- a/.github/workflows/changeset.lock.yml +++ b/.github/workflows/changeset.lock.yml @@ -1775,7 +1775,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml b/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml index 066461f52c7..416b219d904 100644 --- a/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml +++ b/.github/workflows/chaos-pr-bundle-fuzzer.lock.yml @@ -1610,7 +1610,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/ci-coach.lock.yml b/.github/workflows/ci-coach.lock.yml index 34bce8af5d7..6b7a2090107 100644 --- a/.github/workflows/ci-coach.lock.yml +++ b/.github/workflows/ci-coach.lock.yml @@ -1815,7 +1815,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/cloclo.lock.yml b/.github/workflows/cloclo.lock.yml index 55e393dd5ce..1093f840c55 100644 --- a/.github/workflows/cloclo.lock.yml +++ b/.github/workflows/cloclo.lock.yml @@ -2082,7 +2082,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/code-scanning-fixer.lock.yml b/.github/workflows/code-scanning-fixer.lock.yml index 7310b79099b..82052a1c2cd 100644 --- a/.github/workflows/code-scanning-fixer.lock.yml +++ b/.github/workflows/code-scanning-fixer.lock.yml @@ -1740,7 +1740,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/code-simplifier.lock.yml b/.github/workflows/code-simplifier.lock.yml index 993cddd0682..0947b987cfa 100644 --- a/.github/workflows/code-simplifier.lock.yml +++ b/.github/workflows/code-simplifier.lock.yml @@ -1763,7 +1763,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/craft.lock.yml b/.github/workflows/craft.lock.yml index 5ff30a1980f..8b5e5e63bf4 100644 --- a/.github/workflows/craft.lock.yml +++ b/.github/workflows/craft.lock.yml @@ -1755,7 +1755,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml b/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml index 1fc0eabeb16..6b02b0c45d6 100644 --- a/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml +++ b/.github/workflows/daily-agent-of-the-day-blog-writer.lock.yml @@ -1968,7 +1968,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-architecture-diagram.lock.yml b/.github/workflows/daily-architecture-diagram.lock.yml index 07195717700..5f6c5208c04 100644 --- a/.github/workflows/daily-architecture-diagram.lock.yml +++ b/.github/workflows/daily-architecture-diagram.lock.yml @@ -1845,7 +1845,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-astrostylelite-markdown-spellcheck.lock.yml b/.github/workflows/daily-astrostylelite-markdown-spellcheck.lock.yml index 3822a796cd6..68bb18af149 100644 --- a/.github/workflows/daily-astrostylelite-markdown-spellcheck.lock.yml +++ b/.github/workflows/daily-astrostylelite-markdown-spellcheck.lock.yml @@ -1788,7 +1788,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-caveman-optimizer.lock.yml b/.github/workflows/daily-caveman-optimizer.lock.yml index c33f0fc6bd7..56d0442ebeb 100644 --- a/.github/workflows/daily-caveman-optimizer.lock.yml +++ b/.github/workflows/daily-caveman-optimizer.lock.yml @@ -1837,7 +1837,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-community-attribution.lock.yml b/.github/workflows/daily-community-attribution.lock.yml index c79f4e582d9..dc0e4445bb5 100644 --- a/.github/workflows/daily-community-attribution.lock.yml +++ b/.github/workflows/daily-community-attribution.lock.yml @@ -1954,7 +1954,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml b/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml index 6ca56b259f6..24bb8658856 100644 --- a/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml +++ b/.github/workflows/daily-compiler-threat-spec-optimizer.lock.yml @@ -1682,7 +1682,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-doc-healer.lock.yml b/.github/workflows/daily-doc-healer.lock.yml index 9797ee3e231..446d3c84606 100644 --- a/.github/workflows/daily-doc-healer.lock.yml +++ b/.github/workflows/daily-doc-healer.lock.yml @@ -1946,7 +1946,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-doc-updater.lock.yml b/.github/workflows/daily-doc-updater.lock.yml index a8c4e661245..debd08ba01c 100644 --- a/.github/workflows/daily-doc-updater.lock.yml +++ b/.github/workflows/daily-doc-updater.lock.yml @@ -1742,7 +1742,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-rendering-scripts-verifier.lock.yml b/.github/workflows/daily-rendering-scripts-verifier.lock.yml index e60cf83ea48..59655646c45 100644 --- a/.github/workflows/daily-rendering-scripts-verifier.lock.yml +++ b/.github/workflows/daily-rendering-scripts-verifier.lock.yml @@ -1952,7 +1952,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-safe-output-integrator.lock.yml b/.github/workflows/daily-safe-output-integrator.lock.yml index 8a1aa0234fd..5fa84963c67 100644 --- a/.github/workflows/daily-safe-output-integrator.lock.yml +++ b/.github/workflows/daily-safe-output-integrator.lock.yml @@ -1720,7 +1720,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-safeoutputs-git-simulator.lock.yml b/.github/workflows/daily-safeoutputs-git-simulator.lock.yml index cd75b360cbe..a87392f1132 100644 --- a/.github/workflows/daily-safeoutputs-git-simulator.lock.yml +++ b/.github/workflows/daily-safeoutputs-git-simulator.lock.yml @@ -1874,7 +1874,6 @@ jobs: with: persist-credentials: true fetch-depth: 0 - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Fetch additional refs if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') || (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/daily-workflow-updater.lock.yml b/.github/workflows/daily-workflow-updater.lock.yml index 381a5b119e5..14063778318 100644 --- a/.github/workflows/daily-workflow-updater.lock.yml +++ b/.github/workflows/daily-workflow-updater.lock.yml @@ -1640,7 +1640,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/daily-yamllint-fixer.lock.yml b/.github/workflows/daily-yamllint-fixer.lock.yml index 2f8bd10bcd8..84289d27498 100644 --- a/.github/workflows/daily-yamllint-fixer.lock.yml +++ b/.github/workflows/daily-yamllint-fixer.lock.yml @@ -1772,7 +1772,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/dead-code-remover.lock.yml b/.github/workflows/dead-code-remover.lock.yml index cd71ddbab0f..bc5dc2d20d1 100644 --- a/.github/workflows/dead-code-remover.lock.yml +++ b/.github/workflows/dead-code-remover.lock.yml @@ -1768,7 +1768,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/dependabot-burner.lock.yml b/.github/workflows/dependabot-burner.lock.yml index e1108815698..2c8a05ddee6 100644 --- a/.github/workflows/dependabot-burner.lock.yml +++ b/.github/workflows/dependabot-burner.lock.yml @@ -1857,7 +1857,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/dependabot-repair.lock.yml b/.github/workflows/dependabot-repair.lock.yml index 6b9556cb413..75fd020f470 100644 --- a/.github/workflows/dependabot-repair.lock.yml +++ b/.github/workflows/dependabot-repair.lock.yml @@ -1783,7 +1783,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/design-decision-gate.lock.yml b/.github/workflows/design-decision-gate.lock.yml index 2bfe4926420..208637f7fb1 100644 --- a/.github/workflows/design-decision-gate.lock.yml +++ b/.github/workflows/design-decision-gate.lock.yml @@ -1911,7 +1911,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/developer-docs-consolidator.lock.yml b/.github/workflows/developer-docs-consolidator.lock.yml index 659e42c6426..478e65602ee 100644 --- a/.github/workflows/developer-docs-consolidator.lock.yml +++ b/.github/workflows/developer-docs-consolidator.lock.yml @@ -1985,7 +1985,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/dictation-prompt.lock.yml b/.github/workflows/dictation-prompt.lock.yml index 5f473929d32..7fbb9eea253 100644 --- a/.github/workflows/dictation-prompt.lock.yml +++ b/.github/workflows/dictation-prompt.lock.yml @@ -1636,7 +1636,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/eslint-miner.lock.yml b/.github/workflows/eslint-miner.lock.yml index b213f616571..22d22e0b95c 100644 --- a/.github/workflows/eslint-miner.lock.yml +++ b/.github/workflows/eslint-miner.lock.yml @@ -1657,7 +1657,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/functional-pragmatist.lock.yml b/.github/workflows/functional-pragmatist.lock.yml index 3d15ef76c86..41fcef09671 100644 --- a/.github/workflows/functional-pragmatist.lock.yml +++ b/.github/workflows/functional-pragmatist.lock.yml @@ -1640,7 +1640,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/github-mcp-tools-report.lock.yml b/.github/workflows/github-mcp-tools-report.lock.yml index 7f2cf37c52e..1648ac9a597 100644 --- a/.github/workflows/github-mcp-tools-report.lock.yml +++ b/.github/workflows/github-mcp-tools-report.lock.yml @@ -1777,7 +1777,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/glossary-maintainer.lock.yml b/.github/workflows/glossary-maintainer.lock.yml index 87c1120ebc8..1b7c4a7918d 100644 --- a/.github/workflows/glossary-maintainer.lock.yml +++ b/.github/workflows/glossary-maintainer.lock.yml @@ -1887,7 +1887,6 @@ jobs: with: persist-credentials: true fetch-depth: 0 - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/go-logger.lock.yml b/.github/workflows/go-logger.lock.yml index e4e91b773fc..cbf2b61889d 100644 --- a/.github/workflows/go-logger.lock.yml +++ b/.github/workflows/go-logger.lock.yml @@ -1796,7 +1796,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/hourly-ci-cleaner.lock.yml b/.github/workflows/hourly-ci-cleaner.lock.yml index fbd6c1a9312..b6ef25c31fe 100644 --- a/.github/workflows/hourly-ci-cleaner.lock.yml +++ b/.github/workflows/hourly-ci-cleaner.lock.yml @@ -1802,7 +1802,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/instructions-janitor.lock.yml b/.github/workflows/instructions-janitor.lock.yml index e28c84f9da4..2ea2d2cf393 100644 --- a/.github/workflows/instructions-janitor.lock.yml +++ b/.github/workflows/instructions-janitor.lock.yml @@ -1772,7 +1772,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/jsweep.lock.yml b/.github/workflows/jsweep.lock.yml index 30d43e1d635..ae8c52e3715 100644 --- a/.github/workflows/jsweep.lock.yml +++ b/.github/workflows/jsweep.lock.yml @@ -1707,7 +1707,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/layout-spec-maintainer.lock.yml b/.github/workflows/layout-spec-maintainer.lock.yml index 88ee4c7df34..e6f1076455e 100644 --- a/.github/workflows/layout-spec-maintainer.lock.yml +++ b/.github/workflows/layout-spec-maintainer.lock.yml @@ -1687,7 +1687,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/linter-miner.lock.yml b/.github/workflows/linter-miner.lock.yml index 7559bd62814..c54ed48fc01 100644 --- a/.github/workflows/linter-miner.lock.yml +++ b/.github/workflows/linter-miner.lock.yml @@ -1732,7 +1732,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/mergefest.lock.yml b/.github/workflows/mergefest.lock.yml index 6dd92ff0183..0d3f14be7c1 100644 --- a/.github/workflows/mergefest.lock.yml +++ b/.github/workflows/mergefest.lock.yml @@ -1797,7 +1797,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/necromancer.lock.yml b/.github/workflows/necromancer.lock.yml index 4f86a5e3ea8..aefc771407c 100644 --- a/.github/workflows/necromancer.lock.yml +++ b/.github/workflows/necromancer.lock.yml @@ -1872,7 +1872,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/pr-sous-chef.lock.yml b/.github/workflows/pr-sous-chef.lock.yml index 71423e7d18f..9024eccfafe 100644 --- a/.github/workflows/pr-sous-chef.lock.yml +++ b/.github/workflows/pr-sous-chef.lock.yml @@ -1911,7 +1911,6 @@ jobs: with: persist-credentials: true fetch-depth: 0 - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Fetch additional refs if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/q.lock.yml b/.github/workflows/q.lock.yml index c05fac36fa0..84dbf66d780 100644 --- a/.github/workflows/q.lock.yml +++ b/.github/workflows/q.lock.yml @@ -1946,7 +1946,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/refiner.lock.yml b/.github/workflows/refiner.lock.yml index b246a244045..a9cf96cfecf 100644 --- a/.github/workflows/refiner.lock.yml +++ b/.github/workflows/refiner.lock.yml @@ -1817,7 +1817,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/ruflo-backed-task.lock.yml b/.github/workflows/ruflo-backed-task.lock.yml index d7ef51b2dbb..d0739efb7a5 100644 --- a/.github/workflows/ruflo-backed-task.lock.yml +++ b/.github/workflows/ruflo-backed-task.lock.yml @@ -1910,7 +1910,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/schema-feature-coverage.lock.yml b/.github/workflows/schema-feature-coverage.lock.yml index 8e84c10e19f..b404f78d28c 100644 --- a/.github/workflows/schema-feature-coverage.lock.yml +++ b/.github/workflows/schema-feature-coverage.lock.yml @@ -1745,7 +1745,6 @@ jobs: with: persist-credentials: true fetch-depth: 1 - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/slide-deck-maintainer.lock.yml b/.github/workflows/slide-deck-maintainer.lock.yml index e57f19d39a3..29813951831 100644 --- a/.github/workflows/slide-deck-maintainer.lock.yml +++ b/.github/workflows/slide-deck-maintainer.lock.yml @@ -1834,7 +1834,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/smoke-create-cross-repo-pr.lock.yml b/.github/workflows/smoke-create-cross-repo-pr.lock.yml index b54d9daa24d..1226ba3a8b1 100644 --- a/.github/workflows/smoke-create-cross-repo-pr.lock.yml +++ b/.github/workflows/smoke-create-cross-repo-pr.lock.yml @@ -1876,7 +1876,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_SIDE_REPO_PAT }} - name: Checkout github/gh-aw-side-repo into gh-aw-side-repo if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/.github/workflows/smoke-multi-pr.lock.yml b/.github/workflows/smoke-multi-pr.lock.yml index cb6b7927cdf..a1435947f4b 100644 --- a/.github/workflows/smoke-multi-pr.lock.yml +++ b/.github/workflows/smoke-multi-pr.lock.yml @@ -1826,7 +1826,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/smoke-project.lock.yml b/.github/workflows/smoke-project.lock.yml index 7d8c331f3ed..ab33c7df87b 100644 --- a/.github/workflows/smoke-project.lock.yml +++ b/.github/workflows/smoke-project.lock.yml @@ -2085,7 +2085,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/smoke-update-cross-repo-pr.lock.yml b/.github/workflows/smoke-update-cross-repo-pr.lock.yml index 4288147a3b6..1c405cbc380 100644 --- a/.github/workflows/smoke-update-cross-repo-pr.lock.yml +++ b/.github/workflows/smoke-update-cross-repo-pr.lock.yml @@ -1910,7 +1910,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_SIDE_REPO_PAT }} - name: Checkout github/gh-aw-side-repo into gh-aw-side-repo if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 diff --git a/.github/workflows/spec-enforcer.lock.yml b/.github/workflows/spec-enforcer.lock.yml index 5cf82ce5b62..9b578a2f710 100644 --- a/.github/workflows/spec-enforcer.lock.yml +++ b/.github/workflows/spec-enforcer.lock.yml @@ -1665,7 +1665,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/spec-extractor.lock.yml b/.github/workflows/spec-extractor.lock.yml index 696a3915cb9..3c4824d6baa 100644 --- a/.github/workflows/spec-extractor.lock.yml +++ b/.github/workflows/spec-extractor.lock.yml @@ -1766,7 +1766,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/technical-doc-writer.lock.yml b/.github/workflows/technical-doc-writer.lock.yml index f3519dd1835..be5a0354e2d 100644 --- a/.github/workflows/technical-doc-writer.lock.yml +++ b/.github/workflows/technical-doc-writer.lock.yml @@ -1891,7 +1891,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/test-create-pr-error-handling.lock.yml b/.github/workflows/test-create-pr-error-handling.lock.yml index c53694ac423..4730710f109 100644 --- a/.github/workflows/test-create-pr-error-handling.lock.yml +++ b/.github/workflows/test-create-pr-error-handling.lock.yml @@ -1700,7 +1700,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/tidy.lock.yml b/.github/workflows/tidy.lock.yml index 889e3683d66..8917bd994d3 100644 --- a/.github/workflows/tidy.lock.yml +++ b/.github/workflows/tidy.lock.yml @@ -1843,7 +1843,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') || (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'push_to_pull_request_branch') env: diff --git a/.github/workflows/ubuntu-image-analyzer.lock.yml b/.github/workflows/ubuntu-image-analyzer.lock.yml index 96f23d6a372..f7594f6f1fc 100644 --- a/.github/workflows/ubuntu-image-analyzer.lock.yml +++ b/.github/workflows/ubuntu-image-analyzer.lock.yml @@ -1741,7 +1741,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/unbloat-docs.lock.yml b/.github/workflows/unbloat-docs.lock.yml index c926fc82480..a127049a0a1 100644 --- a/.github/workflows/unbloat-docs.lock.yml +++ b/.github/workflows/unbloat-docs.lock.yml @@ -1846,7 +1846,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/update-astro.lock.yml b/.github/workflows/update-astro.lock.yml index 0e96f5dbf3d..4c9a91e1c55 100644 --- a/.github/workflows/update-astro.lock.yml +++ b/.github/workflows/update-astro.lock.yml @@ -1762,7 +1762,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/weekly-blog-post-writer.lock.yml b/.github/workflows/weekly-blog-post-writer.lock.yml index 12164c6114b..5d6da991848 100644 --- a/.github/workflows/weekly-blog-post-writer.lock.yml +++ b/.github/workflows/weekly-blog-post-writer.lock.yml @@ -2033,7 +2033,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/weekly-editors-health-check.lock.yml b/.github/workflows/weekly-editors-health-check.lock.yml index b5e829a6c6d..38f8282939b 100644 --- a/.github/workflows/weekly-editors-health-check.lock.yml +++ b/.github/workflows/weekly-editors-health-check.lock.yml @@ -1709,7 +1709,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: diff --git a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml index 06f6a82d75a..574b691b74e 100644 --- a/.github/workflows/weekly-safe-outputs-spec-review.lock.yml +++ b/.github/workflows/weekly-safe-outputs-spec-review.lock.yml @@ -1639,7 +1639,6 @@ jobs: uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 with: persist-credentials: true - token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }} - name: Configure Git credentials if: (!cancelled()) && needs.agent.result != 'skipped' && contains(needs.agent.outputs.output_types, 'create_pull_request') env: From eb47cedd7b65091f28c3c43d3e4ffb2c789724e1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 20:49:59 +0000 Subject: [PATCH 5/9] test: add token isolation tests for trial mode and side repos in buildSharedPRCheckoutSteps Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- .../compiler_safe_outputs_steps_test.go | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/pkg/workflow/compiler_safe_outputs_steps_test.go b/pkg/workflow/compiler_safe_outputs_steps_test.go index 4462e4183ec..1259ce4049d 100644 --- a/pkg/workflow/compiler_safe_outputs_steps_test.go +++ b/pkg/workflow/compiler_safe_outputs_steps_test.go @@ -87,6 +87,69 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { "repository: org/trial-repo", }, }, + { + // Trial mode must never inject the safe-outputs push token into the checkout + // with.token field. The trial checkout always uses the standard fallback token + // (GH_AW_GITHUB_MCP_SERVER_TOKEN || GH_AW_GITHUB_TOKEN || GITHUB_TOKEN) regardless + // of what safe-outputs token is configured, so the agent can check out the workflow + // repo under trial identity without needing push credentials. + name: "trial mode does not inject safe-outputs token into checkout", + trialMode: true, + trialRepo: "org/trial-repo", + safeOutputs: &SafeOutputsConfig{ + GitHubToken: "${{ secrets.SAFE_OUTPUTS_TOKEN }}", + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + checkContains: []string{ + // The safe-outputs token must still reach the git-credentials step for push auth. + "GIT_TOKEN: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + }, + checkNotContains: []string{ + // The safe-outputs token must NOT be used as the checkout with.token. + "token: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + }, + }, + { + // Side repos (additional checkouts) must not inherit the safe-outputs push token. + // Only the "Configure Git credentials" step should use it; the checkout step itself + // must leave token: unset so actions/checkout uses the default GITHUB_TOKEN. + name: "side repo checkout does not inherit safe-outputs token", + safeOutputs: &SafeOutputsConfig{ + GitHubToken: "${{ secrets.SAFE_OUTPUTS_TOKEN }}", + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + checkoutConfigs: []*CheckoutConfig{ + {Repository: "org/sidelib", Path: "sidelib"}, + }, + checkContains: []string{ + // The safe-outputs token must reach the git-credentials step. + "GIT_TOKEN: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + }, + checkNotContains: []string{ + // The safe-outputs token must NOT appear in the side-repo checkout step. + "token: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + }, + }, + { + // When a side repo declares its own checkout token, that token must be used + // for the checkout step and the safe-outputs push token must not override it. + name: "side repo checkout-specific token is not overridden by safe-outputs token", + safeOutputs: &SafeOutputsConfig{ + GitHubToken: "${{ secrets.SAFE_OUTPUTS_TOKEN }}", + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + checkoutConfigs: []*CheckoutConfig{ + {Repository: "org/sidelib", Path: "sidelib", GitHubToken: "${{ secrets.CHECKOUT_TOKEN }}"}, + }, + checkContains: []string{ + // The checkout-specific token must govern the side-repo checkout step. + "token: ${{ secrets.CHECKOUT_TOKEN }}", + }, + checkNotContains: []string{ + // The safe-outputs token must NOT appear as a checkout with.token. + "token: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + }, + }, { name: "create-pr per-config github-token flows into git credentials", safeOutputs: &SafeOutputsConfig{ From e8c2d540d60406786e6a15eeb98543c5d004c04c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 21:50:29 +0000 Subject: [PATCH 6/9] fix: use safe-output token chain for trial mode checkout in safe_outputs job In trial mode, GenerateDefaultCheckoutStep was calling getEffectiveGitHubToken which includes the read-only GH_AW_GITHUB_MCP_SERVER_TOKEN. When keepCredentialsForPush is true (safe_outputs job), use getEffectiveSafeOutputGitHubToken instead so the MCP server token is never injected into a push-capable checkout. Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- pkg/workflow/checkout_manager_test.go | 23 +++++++++++++++++++ pkg/workflow/checkout_step_generator.go | 11 ++++++++- .../compiler_safe_outputs_steps_test.go | 14 +++++++---- 3 files changed, 42 insertions(+), 6 deletions(-) diff --git a/pkg/workflow/checkout_manager_test.go b/pkg/workflow/checkout_manager_test.go index 8047f69063f..57ea583d6ec 100644 --- a/pkg/workflow/checkout_manager_test.go +++ b/pkg/workflow/checkout_manager_test.go @@ -311,6 +311,29 @@ func TestCheckoutPushTokenIsolation(t *testing.T) { assert.NotContains(t, combined, pushToken, "pushToken must not override an explicit checkout token") assert.Equal(t, 1, strings.Count(combined, "token: "), "token must be emitted exactly once") }) + + t.Run("trial mode in safe_outputs job uses safe-output token chain not MCP token", func(t *testing.T) { + cm := NewCheckoutManager(nil) + cm.SetKeepCredentialsForPush(true) + cm.SetPushToken(pushToken) + lines := cm.GenerateDefaultCheckoutStep(true, "owner/trial-repo", getPin) + combined := strings.Join(lines, "") + // Trial checkout in safe_outputs must use the safe-output chain (GH_AW_GITHUB_TOKEN || GITHUB_TOKEN). + assert.Contains(t, combined, "token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", "safe_outputs trial mode must use the safe-output token chain") + // The read-only MCP server token must never appear in a safe_outputs checkout. + assert.NotContains(t, combined, "GH_AW_GITHUB_MCP_SERVER_TOKEN", "MCP server token must not appear in a safe_outputs checkout") + // The push token must not appear in the checkout step. + assert.NotContains(t, combined, pushToken, "pushToken must not be injected in trial mode checkout") + }) + + t.Run("trial mode in agent job (not safe_outputs) uses full agent token chain", func(t *testing.T) { + cm := NewCheckoutManager(nil) + // keepCredentialsForPush is false for the agent job. + lines := cm.GenerateDefaultCheckoutStep(true, "owner/trial-repo", getPin) + combined := strings.Join(lines, "") + // Agent trial mode must use the full token chain including the MCP token. + assert.Contains(t, combined, "GH_AW_GITHUB_MCP_SERVER_TOKEN", "agent trial mode should use the full agent token chain") + }) } // TestGenerateAdditionalCheckoutSteps verifies that non-default checkouts are emitted correctly. diff --git a/pkg/workflow/checkout_step_generator.go b/pkg/workflow/checkout_step_generator.go index f264a217547..605ad022b72 100644 --- a/pkg/workflow/checkout_step_generator.go +++ b/pkg/workflow/checkout_step_generator.go @@ -386,7 +386,16 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( if trialLogicalRepoSlug != "" { fmt.Fprintf(&sb, " repository: %s\n", trialLogicalRepoSlug) } - effectiveToken := getEffectiveGitHubToken("") + // In the safe_outputs job (keepCredentialsForPush=true) use the safe-outputs + // token chain (GH_AW_GITHUB_TOKEN || GITHUB_TOKEN), which excludes the + // read-only GH_AW_GITHUB_MCP_SERVER_TOKEN that is scoped to the MCP server + // and is never appropriate for a push-capable checkout. + var effectiveToken string + if cm.keepCredentialsForPush { + effectiveToken = getEffectiveSafeOutputGitHubToken("") + } else { + effectiveToken = getEffectiveGitHubToken("") + } fmt.Fprintf(&sb, " token: %s\n", effectiveToken) } diff --git a/pkg/workflow/compiler_safe_outputs_steps_test.go b/pkg/workflow/compiler_safe_outputs_steps_test.go index 1259ce4049d..745a0769602 100644 --- a/pkg/workflow/compiler_safe_outputs_steps_test.go +++ b/pkg/workflow/compiler_safe_outputs_steps_test.go @@ -88,11 +88,11 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { }, }, { - // Trial mode must never inject the safe-outputs push token into the checkout - // with.token field. The trial checkout always uses the standard fallback token - // (GH_AW_GITHUB_MCP_SERVER_TOKEN || GH_AW_GITHUB_TOKEN || GITHUB_TOKEN) regardless - // of what safe-outputs token is configured, so the agent can check out the workflow - // repo under trial identity without needing push credentials. + // Trial mode within safe_outputs must use the safe-outputs token chain + // (GH_AW_GITHUB_TOKEN || GITHUB_TOKEN) for the checkout, not the agent + // token chain that includes the read-only GH_AW_GITHUB_MCP_SERVER_TOKEN. + // The safe-outputs push token still reaches GIT_TOKEN in the "Configure Git + // credentials" step for push operations. name: "trial mode does not inject safe-outputs token into checkout", trialMode: true, trialRepo: "org/trial-repo", @@ -103,10 +103,14 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { checkContains: []string{ // The safe-outputs token must still reach the git-credentials step for push auth. "GIT_TOKEN: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + // Trial mode checkout must use the safe-outputs token chain (no MCP token). + "token: ${{ secrets.GH_AW_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}", }, checkNotContains: []string{ // The safe-outputs token must NOT be used as the checkout with.token. "token: ${{ secrets.SAFE_OUTPUTS_TOKEN }}", + // The read-only MCP server token must never appear in a safe_outputs checkout. + "GH_AW_GITHUB_MCP_SERVER_TOKEN", }, }, { From 530b917157688b124261f83901bfb352ac8571b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:24:04 +0000 Subject: [PATCH 7/9] fix: clear http.extraheader after git remote set-url to prevent cross-org auth conflicts Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- actions/setup/sh/configure_git_credentials.sh | 5 +++ pkg/workflow/checkout_manager_test.go | 39 +++++++++++++++++++ pkg/workflow/checkout_step_generator.go | 11 +++++- .../compiler_safe_outputs_steps_test.go | 34 ++++++++++++++++ pkg/workflow/git_config_test.go | 31 ++++++++++++++- 5 files changed, 117 insertions(+), 3 deletions(-) diff --git a/actions/setup/sh/configure_git_credentials.sh b/actions/setup/sh/configure_git_credentials.sh index a2bb4075fd9..3722b95f7a5 100755 --- a/actions/setup/sh/configure_git_credentials.sh +++ b/actions/setup/sh/configure_git_credentials.sh @@ -94,6 +94,11 @@ TOKEN="${GITHUB_TOKEN:-${GIT_TOKEN:-}}" if [ -n "${REPO}" ] && [ -n "${URL}" ] && [ -n "${TOKEN}" ]; then URL_STRIPPED="${URL#https://}" git remote set-url origin "https://x-access-token:${TOKEN}@${URL_STRIPPED}/${REPO}.git" + # Remove the http.extraheader that actions/checkout persists with persist-credentials: true. + # Without this, git sends two conflicting Authorization headers (the checkout token via + # extraheader + the push token via the URL), which can fail in cross-org setups where + # the checkout token is scoped to a different org than the push target. + git config --unset-all "http.${URL}/.extraheader" 2>/dev/null || true fi echo "Git configured with standard GitHub Actions identity" >&2 diff --git a/pkg/workflow/checkout_manager_test.go b/pkg/workflow/checkout_manager_test.go index 57ea583d6ec..5674c0eb38d 100644 --- a/pkg/workflow/checkout_manager_test.go +++ b/pkg/workflow/checkout_manager_test.go @@ -1689,4 +1689,43 @@ func TestGenerateConfigureGitCredentialsSteps(t *testing.T) { assert.Contains(t, combined, `${GH_AW_SUBREPO_0}.git`) assert.Contains(t, combined, `${GH_AW_SUBREPO_1}.git`) }) + + // Regression: when persist-credentials: true is used in actions/checkout, it stores + // an http./.extraheader in .git/config. Without explicit cleanup, git sends + // two conflicting Authorization headers (checkout token via extraheader + push token + // via URL), causing failures in cross-org scenarios where the checkout token is + // scoped to a different org than the push target. + t.Run("multi-repo clears http extraheader after remote set-url for each sub-repo", func(t *testing.T) { + cm := NewCheckoutManager([]*CheckoutConfig{ + {Repository: "org/other-repo", Path: "./other-repo"}, + }) + steps := cm.GenerateConfigureGitCredentialsSteps(token, alwaysTrue) + combined := strings.Join(steps, "") + + assert.Contains(t, combined, `config --unset-all "http.${GITHUB_SERVER_URL}/.extraheader"`, + "must clear the extraheader that actions/checkout persists with persist-credentials: true") + // The cleanup must be idempotent (2>/dev/null || true) so it doesn't fail when no extraheader was set. + assert.Contains(t, combined, "2>/dev/null || true", + "extraheader cleanup must be idempotent") + }) + + t.Run("cross-org push: sub-repo cleanup appears after remote set-url", func(t *testing.T) { + // Regression: in cross-org setups (checkout repo = workflow-org/workflow-repo, + // push target = target-org/target-repo), actions/checkout persists the workflow-org + // checkout token as an extraheader. GenerateConfigureGitCredentialsSteps must unset + // that extraheader after rewriting the remote URL to use the push token, so that + // the only credential used for push is the push token. + cm := NewCheckoutManager([]*CheckoutConfig{ + {Repository: "target-org/target-repo", Path: "./target-repo"}, + }) + steps := cm.GenerateConfigureGitCredentialsSteps(token, alwaysTrue) + combined := strings.Join(steps, "") + + remoteSetUrlIdx := strings.Index(combined, "remote set-url origin") + unsetExtraheaderIdx := strings.Index(combined, "config --unset-all") + require.Greater(t, remoteSetUrlIdx, -1, "remote set-url must be present") + require.Greater(t, unsetExtraheaderIdx, -1, "extraheader cleanup must be present") + assert.Greater(t, unsetExtraheaderIdx, remoteSetUrlIdx, + "extraheader cleanup must follow remote set-url so the push token is the sole credential") + }) } diff --git a/pkg/workflow/checkout_step_generator.go b/pkg/workflow/checkout_step_generator.go index 605ad022b72..f523d8bbd06 100644 --- a/pkg/workflow/checkout_step_generator.go +++ b/pkg/workflow/checkout_step_generator.go @@ -337,6 +337,10 @@ func (cm *CheckoutManager) GenerateConfigureGitCredentialsSteps(gitRemoteToken s steps = append(steps, fmt.Sprintf(" # Re-authenticate git for %s\n", commentRef), fmt.Sprintf(" git -C %s remote set-url origin \"https://x-access-token:${GIT_TOKEN}@${GIT_SERVER_URL_STRIPPED}/${%s}.git\"\n", gitDir, repo.envVarName), + // Remove the http.extraheader that actions/checkout persists with persist-credentials: true. + // Without this, git sends two conflicting Authorization headers (checkout token via + // extraheader + push token via URL), which breaks cross-org push scenarios. + fmt.Sprintf(" git -C %s config --unset-all \"http.${GITHUB_SERVER_URL}/.extraheader\" 2>/dev/null || true\n", gitDir), ) } steps = append(steps, @@ -402,8 +406,11 @@ func (cm *CheckoutManager) GenerateDefaultCheckoutStep( // Apply user overrides only when NOT in trial mode to avoid conflicting // repository/token values in the same checkout step. Note that safe_outputs push // auth is intentionally isolated from checkout auth: this step only emits tokens - // from checkout config (or trial mode), while push auth is applied later by - // CheckoutManager.GenerateConfigureGitCredentialsSteps. + // from checkout config (or trial mode). Push auth is applied later by + // CheckoutManager.GenerateConfigureGitCredentialsSteps, which also calls + // git config --unset-all http./.extraheader to remove the extraheader that + // actions/checkout persists with persist-credentials: true, preventing conflicting + // Authorization headers in cross-org push scenarios. if !trialMode && override != nil { if override.key.wiki { // Wiki checkout: use "{repository}.wiki" as the effective repository. diff --git a/pkg/workflow/compiler_safe_outputs_steps_test.go b/pkg/workflow/compiler_safe_outputs_steps_test.go index 745a0769602..415e58c327b 100644 --- a/pkg/workflow/compiler_safe_outputs_steps_test.go +++ b/pkg/workflow/compiler_safe_outputs_steps_test.go @@ -258,6 +258,40 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { "name: Checkout repository", // Subdirectory checkout is re-authenticated so the handler can push to it. `git -C "a" remote set-url origin`, + // Regression: extraheader from actions/checkout (persist-credentials: true) must + // be cleared so the push token (not the checkout token) is the sole credential. + `git -C "a" config --unset-all "http.${GITHUB_SERVER_URL}/.extraheader"`, + }, + }, + { + // Regression for cross-org push failure: when a safe_outputs github-app is + // configured to push to a target org, actions/checkout stores the workflow-org + // checkout token as an http.extraheader. Without explicit cleanup, git pushes to + // the target org send two conflicting Authorization headers, failing the push. + // The "Configure Git credentials" step must clear the extraheader for sub-repos. + name: "safe-outputs github-app cross-org: extraheader cleared for sub-repo checkout", + safeOutputs: &SafeOutputsConfig{ + GitHubApp: &GitHubAppConfig{ + AppID: "${{ vars.APP_ID }}", + PrivateKey: "${{ secrets.APP_PRIVATE_KEY }}", + }, + CreatePullRequests: &CreatePullRequestsConfig{}, + }, + checkoutConfigs: []*CheckoutConfig{ + {Repository: "target-org/target-repo", Path: "target-repo"}, + }, + checkContains: []string{ + // The app token must reach the git-credentials step for push auth. + "GIT_TOKEN: ${{ steps.safe-outputs-app-token.outputs.token }}", + // The sub-repo remote must be rewritten to use the push token. + `git -C "target-repo" remote set-url origin`, + // The extraheader from the default GITHUB_TOKEN checkout must be cleared + // to prevent conflicting auth headers in the cross-org push. + `git -C "target-repo" config --unset-all "http.${GITHUB_SERVER_URL}/.extraheader"`, + }, + checkNotContains: []string{ + // The app token must NOT appear as a checkout with.token. + "token: ${{ steps.safe-outputs-app-token.outputs.token }}", }, }, { diff --git a/pkg/workflow/git_config_test.go b/pkg/workflow/git_config_test.go index 30d07048a4c..56c50777f32 100644 --- a/pkg/workflow/git_config_test.go +++ b/pkg/workflow/git_config_test.go @@ -218,7 +218,36 @@ func TestCredentialsCleanerStepsHelper(t *testing.T) { }) } -// TestGitConfigurationSkippedWhenCheckoutDisabled verifies that git credential steps +// TestConfigureGitCredentialsShellScript verifies that the configure_git_credentials.sh +// shell script clears the http.extraheader that actions/checkout persists when +// persist-credentials: true is used. Without this, cross-org push scenarios fail because +// git sends two conflicting Authorization headers: the checkout token (via extraheader) +// and the push token (via URL). This is a regression guard for the safe-outputs push-token +// isolation fix. +func TestConfigureGitCredentialsShellScript(t *testing.T) { + scriptPath := filepath.Join("..", "..", "actions", "setup", "sh", "configure_git_credentials.sh") + content, err := os.ReadFile(scriptPath) + if err != nil { + t.Fatalf("Failed to read configure_git_credentials.sh: %v", err) + } + scriptContent := string(content) + + // Regression: the script must unset the http.extraheader that actions/checkout + // persists with persist-credentials: true to prevent conflicting Authorization + // headers in cross-org push scenarios. + if !strings.Contains(scriptContent, "--unset-all") { + t.Error("configure_git_credentials.sh must call git config --unset-all to clear the persisted extraheader") + } + if !strings.Contains(scriptContent, "extraheader") { + t.Error("configure_git_credentials.sh must reference extraheader in the cleanup command") + } + // The cleanup must be idempotent (2>/dev/null || true) so it doesn't fail when no + // extraheader was set (e.g. when persist-credentials: false was used). + if !strings.Contains(scriptContent, "2>/dev/null || true") { + t.Error("configure_git_credentials.sh extraheader cleanup must be idempotent (2>/dev/null || true)") + } +} + // are not emitted when checkout: false is set in the workflow frontmatter. func TestGitConfigurationSkippedWhenCheckoutDisabled(t *testing.T) { tmpDir := testutil.TempDir(t, "git-config-checkout-false-test") From c4d23d9e4e65ca38de935da3e20aac7ecc920090 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:28:10 +0000 Subject: [PATCH 8/9] fix: strengthen test assertions for extraheader cleanup and clarify URL variable intent Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- pkg/workflow/checkout_step_generator.go | 3 +++ pkg/workflow/git_config_test.go | 11 +++++------ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/pkg/workflow/checkout_step_generator.go b/pkg/workflow/checkout_step_generator.go index f523d8bbd06..36efce1dc3f 100644 --- a/pkg/workflow/checkout_step_generator.go +++ b/pkg/workflow/checkout_step_generator.go @@ -340,6 +340,9 @@ func (cm *CheckoutManager) GenerateConfigureGitCredentialsSteps(gitRemoteToken s // Remove the http.extraheader that actions/checkout persists with persist-credentials: true. // Without this, git sends two conflicting Authorization headers (checkout token via // extraheader + push token via URL), which breaks cross-org push scenarios. + // Note: GITHUB_SERVER_URL (e.g. "https://github.com") is the full URL used as the + // git config key; GIT_SERVER_URL_STRIPPED (e.g. "github.com") is only used in the + // token-in-URL remote string above — these are intentionally different variables. fmt.Sprintf(" git -C %s config --unset-all \"http.${GITHUB_SERVER_URL}/.extraheader\" 2>/dev/null || true\n", gitDir), ) } diff --git a/pkg/workflow/git_config_test.go b/pkg/workflow/git_config_test.go index 56c50777f32..951cbab3718 100644 --- a/pkg/workflow/git_config_test.go +++ b/pkg/workflow/git_config_test.go @@ -234,12 +234,11 @@ func TestConfigureGitCredentialsShellScript(t *testing.T) { // Regression: the script must unset the http.extraheader that actions/checkout // persists with persist-credentials: true to prevent conflicting Authorization - // headers in cross-org push scenarios. - if !strings.Contains(scriptContent, "--unset-all") { - t.Error("configure_git_credentials.sh must call git config --unset-all to clear the persisted extraheader") - } - if !strings.Contains(scriptContent, "extraheader") { - t.Error("configure_git_credentials.sh must reference extraheader in the cleanup command") + // headers in cross-org push scenarios. Check for both tokens together in a single + // git config command so the test can't be satisfied by unrelated uses of either token. + const unsetExtraheaderCmd = `config --unset-all "http.` + if !strings.Contains(scriptContent, unsetExtraheaderCmd) || !strings.Contains(scriptContent, `/.extraheader"`) { + t.Error(`configure_git_credentials.sh must contain: git config --unset-all "http./.extraheader"`) } // The cleanup must be idempotent (2>/dev/null || true) so it doesn't fail when no // extraheader was set (e.g. when persist-credentials: false was used). From e9c0d1a1fe5b22de883933862037af44ffae8a6c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 23:50:04 +0000 Subject: [PATCH 9/9] test: add persist-credentials: true regression guard for safe-outputs github-app checkout path Co-authored-by: gh-aw-bot <259018956+gh-aw-bot@users.noreply.github.com> --- .github/workflows/smoke-create-cross-repo-pr.lock.yml | 1 + .github/workflows/smoke-update-cross-repo-pr.lock.yml | 1 + pkg/workflow/compiler_safe_outputs_steps_test.go | 9 +++++++++ 3 files changed, 11 insertions(+) diff --git a/.github/workflows/smoke-create-cross-repo-pr.lock.yml b/.github/workflows/smoke-create-cross-repo-pr.lock.yml index 1226ba3a8b1..dfe5fc04277 100644 --- a/.github/workflows/smoke-create-cross-repo-pr.lock.yml +++ b/.github/workflows/smoke-create-cross-repo-pr.lock.yml @@ -1896,6 +1896,7 @@ jobs: GIT_SERVER_URL_STRIPPED="${GITHUB_SERVER_URL#https://}" # Re-authenticate git for gh-aw-side-repo git -C "gh-aw-side-repo" remote set-url origin "https://x-access-token:${GIT_TOKEN}@${GIT_SERVER_URL_STRIPPED}/${GH_AW_SUBREPO_0}.git" + git -C "gh-aw-side-repo" config --unset-all "http.${GITHUB_SERVER_URL}/.extraheader" 2>/dev/null || true echo "Git configured with standard GitHub Actions identity" - name: Configure GH_HOST for enterprise compatibility id: ghes-host-config diff --git a/.github/workflows/smoke-update-cross-repo-pr.lock.yml b/.github/workflows/smoke-update-cross-repo-pr.lock.yml index 1c405cbc380..a3c02170e86 100644 --- a/.github/workflows/smoke-update-cross-repo-pr.lock.yml +++ b/.github/workflows/smoke-update-cross-repo-pr.lock.yml @@ -1938,6 +1938,7 @@ jobs: GIT_SERVER_URL_STRIPPED="${GITHUB_SERVER_URL#https://}" # Re-authenticate git for gh-aw-side-repo git -C "gh-aw-side-repo" remote set-url origin "https://x-access-token:${GIT_TOKEN}@${GIT_SERVER_URL_STRIPPED}/${GH_AW_SUBREPO_0}.git" + git -C "gh-aw-side-repo" config --unset-all "http.${GITHUB_SERVER_URL}/.extraheader" 2>/dev/null || true echo "Git configured with standard GitHub Actions identity" - name: Configure GH_HOST for enterprise compatibility id: ghes-host-config diff --git a/pkg/workflow/compiler_safe_outputs_steps_test.go b/pkg/workflow/compiler_safe_outputs_steps_test.go index 415e58c327b..6bdb8444e05 100644 --- a/pkg/workflow/compiler_safe_outputs_steps_test.go +++ b/pkg/workflow/compiler_safe_outputs_steps_test.go @@ -181,6 +181,10 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { }, }, { + // Regression guard: safe_outputs github-app push token must NOT override the + // checkout token. The checkout step must retain credentials (persist-credentials: true) + // for git operations, but the app token is only used for push auth via GIT_TOKEN — + // it must never appear as checkout with.token. name: "safe-outputs github-app token is not used by checkout step", safeOutputs: &SafeOutputsConfig{ GitHubApp: &GitHubAppConfig{ @@ -191,9 +195,14 @@ func TestBuildSharedPRCheckoutSteps(t *testing.T) { }, checkContains: []string{ "GIT_TOKEN: ${{ steps.safe-outputs-app-token.outputs.token }}", + // Regression: persist-credentials must be true so git operations work; + // the app token is NOT what drives checkout auth. + "persist-credentials: true", }, checkNotContains: []string{ "token: ${{ steps.safe-outputs-app-token.outputs.token }}", + // Credentials must NOT be stripped in the safe_outputs job. + "persist-credentials: false", }, }, {