From e1d91899ae0f50c9f9cdf5d932b5c8291d870066 Mon Sep 17 00:00:00 2001 From: Nathan Moin Vaziri Date: Fri, 5 Jun 2026 11:08:14 -0700 Subject: [PATCH] Pin GIT_CONFIG_GLOBAL to the temp config during global auth setup configureTempGlobalConfig isolates global git config by overriding HOME to a temporary directory. But GIT_CONFIG_GLOBAL takes precedence over HOME when git locates the global config file, so when a workflow already has GIT_CONFIG_GLOBAL set in the environment, 'git config --global' writes land in that file instead of the temporary config. replaceTokenPlaceholder then reads the temporary config, cannot find the placeholder, and fails with 'Unable to replace auth placeholder'. Set GIT_CONFIG_GLOBAL to the temporary config alongside the HOME override so global config operations always target the temp file regardless of any inherited value, and unset it again in removeGlobalConfig. Assisted-By: Claude Opus 4.8 --- __test__/git-auth-helper.test.ts | 21 +++++++++++++++++++++ dist/index.js | 7 ++++++- src/git-auth-helper.ts | 8 +++++++- 3 files changed, 34 insertions(+), 2 deletions(-) diff --git a/__test__/git-auth-helper.test.ts b/__test__/git-auth-helper.test.ts index ad3566a..61247f0 100644 --- a/__test__/git-auth-helper.test.ts +++ b/__test__/git-auth-helper.test.ts @@ -902,6 +902,25 @@ describe('git-auth-helper tests', () => { } }) + const configureGlobalAuth_overridesGitConfigGlobal = + 'configureGlobalAuth overrides GIT_CONFIG_GLOBAL' + it(configureGlobalAuth_overridesGitConfigGlobal, async () => { + // Arrange + await setup(configureGlobalAuth_overridesGitConfigGlobal) + const authHelper = gitAuthHelper.createAuthHelper(git, settings) + + // Act + await authHelper.configureAuth() + await authHelper.configureGlobalAuth() + + // Assert GIT_CONFIG_GLOBAL is pinned to the temporary global config, so an + // inherited GIT_CONFIG_GLOBAL cannot redirect --global writes + expect(git.env['HOME']).toBeTruthy() + expect(git.env['GIT_CONFIG_GLOBAL']).toBe( + path.join(git.env['HOME'], '.gitconfig') + ) + }) + const removeGlobalConfig_removesOverride = 'removeGlobalConfig removes override' it(removeGlobalConfig_removesOverride, async () => { @@ -912,6 +931,7 @@ describe('git-auth-helper tests', () => { await authHelper.configureGlobalAuth() const homeOverride = git.env['HOME'] // Sanity check expect(homeOverride).toBeTruthy() + expect(git.env['GIT_CONFIG_GLOBAL']).toBeTruthy() await fs.promises.stat(path.join(git.env['HOME'], '.gitconfig')) // Act @@ -919,6 +939,7 @@ describe('git-auth-helper tests', () => { // Assert expect(git.env['HOME']).toBeUndefined() + expect(git.env['GIT_CONFIG_GLOBAL']).toBeUndefined() try { await fs.promises.stat(homeOverride) throw new Error(`Should have been deleted '${homeOverride}'`) diff --git a/dist/index.js b/dist/index.js index 906b59a..ba9a7d0 100644 --- a/dist/index.js +++ b/dist/index.js @@ -224,6 +224,10 @@ class GitAuthHelper { // Override HOME core.info(`Temporarily overriding HOME='${this.temporaryHomePath}' before making global git config changes`); this.git.setEnvironmentVariable('HOME', this.temporaryHomePath); + // GIT_CONFIG_GLOBAL takes precedence over HOME when locating the global + // config file. Pin it to the temporary config so an inherited + // GIT_CONFIG_GLOBAL cannot redirect our global git config writes elsewhere. + this.git.setEnvironmentVariable('GIT_CONFIG_GLOBAL', newGitConfigPath); return newGitConfigPath; }); } @@ -307,8 +311,9 @@ class GitAuthHelper { return __awaiter(this, void 0, void 0, function* () { var _a; if (((_a = this.temporaryHomePath) === null || _a === void 0 ? void 0 : _a.length) > 0) { - core.debug(`Unsetting HOME override`); + core.debug(`Unsetting HOME and GIT_CONFIG_GLOBAL overrides`); this.git.removeEnvironmentVariable('HOME'); + this.git.removeEnvironmentVariable('GIT_CONFIG_GLOBAL'); yield io.rmRF(this.temporaryHomePath); } }); diff --git a/src/git-auth-helper.ts b/src/git-auth-helper.ts index e67db14..c42d777 100644 --- a/src/git-auth-helper.ts +++ b/src/git-auth-helper.ts @@ -122,6 +122,11 @@ class GitAuthHelper { ) this.git.setEnvironmentVariable('HOME', this.temporaryHomePath) + // GIT_CONFIG_GLOBAL takes precedence over HOME when locating the global + // config file. Pin it to the temporary config so an inherited + // GIT_CONFIG_GLOBAL cannot redirect our global git config writes elsewhere. + this.git.setEnvironmentVariable('GIT_CONFIG_GLOBAL', newGitConfigPath) + return newGitConfigPath } @@ -237,8 +242,9 @@ class GitAuthHelper { async removeGlobalConfig(): Promise { if (this.temporaryHomePath?.length > 0) { - core.debug(`Unsetting HOME override`) + core.debug(`Unsetting HOME and GIT_CONFIG_GLOBAL overrides`) this.git.removeEnvironmentVariable('HOME') + this.git.removeEnvironmentVariable('GIT_CONFIG_GLOBAL') await io.rmRF(this.temporaryHomePath) } }