From cff8d3c8f08ae322e07a1c98ef1b882dc32ddc46 Mon Sep 17 00:00:00 2001 From: Tem Revil <146881507+TemRevil@users.noreply.github.com> Date: Thu, 20 Aug 2026 03:23:23 +0300 Subject: [PATCH] fix(git-config): neutralize checkout credential in include-based config (#1526) configureGitAuth() removed the actions/checkout auth header with `git config --unset-all http./.extraheader`, which only edits the repo-local config. Since actions/checkout v6.0.0 (backported to v5.0.1 and v4.3.1) the header is written to a separate file under RUNNER_TEMP and pulled in via include.path, so --unset-all on the local config is a no-op: the code logged "No existing authentication headers to remove" while the checkout credential (usually the workflow GITHUB_TOKEN) stayed usable by git for the rest of the job. Also clear the header from every included file, so it is neutralized under both the pre-v6 (local) and v6+ (include) layouts. Includes that do not define the header are left untouched. Fixes #1510 --- src/github/operations/git-config.ts | 41 ++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/src/github/operations/git-config.ts b/src/github/operations/git-config.ts index 535a75c4..bf597633 100644 --- a/src/github/operations/git-config.ts +++ b/src/github/operations/git-config.ts @@ -56,6 +56,16 @@ export async function configureGitAuth( * action's own token instead (a credential helper when non-write users are * allowed, otherwise the origin URL). This applies to every mode, including API * commit signing where no other git configuration is needed. + * + * actions/checkout < v6 stored the header directly in the repo-local config, + * where `git config --unset-all` removes it. Since v6.0.0 (backported to + * v5.0.1 and v4.3.1) the header is written to a separate file under + * RUNNER_TEMP that the repo config pulls in via `include.path`; `--unset-all` + * on the local config cannot touch an include-provided value, so the removal + * was a silent no-op and the checkout credential (typically the workflow + * GITHUB_TOKEN) stayed usable by git for the rest of the job. Clear the + * header from the local config AND from every included file so it can no + * longer authenticate while Claude runs. */ export async function replaceCheckoutCredentials( githubToken: string, @@ -65,12 +75,35 @@ export async function replaceCheckoutCredentials( // Remove the authorization header that actions/checkout sets console.log("Removing existing git authentication headers..."); + const extraheaderKey = `http.${GITHUB_SERVER_URL}/.extraheader`; + let removedHeader = false; try { - await $`git config --unset-all http.${GITHUB_SERVER_URL}/.extraheader`; - console.log("✓ Removed existing authentication headers"); - } catch (e) { - console.log("No existing authentication headers to remove"); + await $`git config --unset-all ${extraheaderKey}`; + removedHeader = true; + } catch { + // No extraheader in the local config (expected on the v6+ include layout). } + try { + const includePaths = + await $`git config --local --get-all include.path`.text(); + for (const includePath of includePaths.split("\n")) { + const path = includePath.trim(); + if (!path) continue; + try { + await $`git config --file ${path} --unset-all ${extraheaderKey}`; + removedHeader = true; + } catch { + // This include does not define the header; leave it untouched. + } + } + } catch { + // No include.path entries in the local config. + } + console.log( + removedHeader + ? "✓ Removed existing authentication headers" + : "No existing authentication headers to remove", + ); if (process.env.ALLOWED_NON_WRITE_USERS) { // When processing content from non-write users, use a credential helper