@@ -411,8 +411,50 @@ class GitAuthHelper {
411411 }
412412 removeToken() {
413413 return __awaiter(this, void 0, void 0, function* () {
414- // HTTP extra header
414+ // Remove HTTP extra header from local git config and submodule configs
415415 yield this.removeGitConfig(this.tokenConfigKey);
416+ //
417+ // Cleanup actions/checkout@v6 style credentials
418+ //
419+ const skipV6Cleanup = process.env['ACTIONS_CHECKOUT_SKIP_V6_CLEANUP'];
420+ if (skipV6Cleanup === '1' || (skipV6Cleanup === null || skipV6Cleanup === void 0 ? void 0 : skipV6Cleanup.toLowerCase()) === 'true') {
421+ core.debug('Skipping v6 style cleanup due to ACTIONS_CHECKOUT_SKIP_V6_CLEANUP');
422+ return;
423+ }
424+ try {
425+ // Collect credentials config paths that need to be removed
426+ const credentialsPaths = new Set();
427+ // Remove includeIf entries that point to git-credentials-*.config files
428+ const mainCredentialsPaths = yield this.removeIncludeIfCredentials();
429+ mainCredentialsPaths.forEach(path => credentialsPaths.add(path));
430+ // Remove submodule includeIf entries that point to git-credentials-*.config files
431+ try {
432+ const submoduleConfigPaths = yield this.git.getSubmoduleConfigPaths(true);
433+ for (const configPath of submoduleConfigPaths) {
434+ const submoduleCredentialsPaths = yield this.removeIncludeIfCredentials(configPath);
435+ submoduleCredentialsPaths.forEach(path => credentialsPaths.add(path));
436+ }
437+ }
438+ catch (err) {
439+ core.debug(`Unable to get submodule config paths: ${err}`);
440+ }
441+ // Remove credentials config files
442+ for (const credentialsPath of credentialsPaths) {
443+ // Only remove credentials config files if they are under RUNNER_TEMP
444+ const runnerTemp = process.env['RUNNER_TEMP'];
445+ if (runnerTemp && credentialsPath.startsWith(runnerTemp)) {
446+ try {
447+ yield io.rmRF(credentialsPath);
448+ }
449+ catch (err) {
450+ core.debug(`Failed to remove credentials config '${credentialsPath}': ${err}`);
451+ }
452+ }
453+ }
454+ }
455+ catch (err) {
456+ core.debug(`Failed to cleanup v6 style credentials: ${err}`);
457+ }
416458 });
417459 }
418460 removeGitConfig(configKey_1) {
@@ -430,6 +472,49 @@ class GitAuthHelper {
430472 `sh -c "git config --local --name-only --get-regexp '${pattern}' && git config --local --unset-all '${configKey}' || :"`, true);
431473 });
432474 }
475+ /**
476+ * Removes includeIf entries that point to git-credentials-*.config files.
477+ * This handles cleanup of credentials configured by newer versions of the action.
478+ * @param configPath Optional path to a specific git config file to operate on
479+ * @returns Array of unique credentials config file paths that were found and removed
480+ */
481+ removeIncludeIfCredentials(configPath) {
482+ return __awaiter(this, void 0, void 0, function* () {
483+ const credentialsPaths = new Set();
484+ try {
485+ // Get all includeIf.gitdir keys
486+ const keys = yield this.git.tryGetConfigKeys('^includeIf\\.gitdir:', false, // globalConfig?
487+ configPath);
488+ for (const key of keys) {
489+ // Get all values for this key
490+ const values = yield this.git.tryGetConfigValues(key, false, // globalConfig?
491+ configPath);
492+ if (values.length > 0) {
493+ // Remove only values that match git-credentials-<uuid>.config pattern
494+ for (const value of values) {
495+ if (this.testCredentialsConfigPath(value)) {
496+ credentialsPaths.add(value);
497+ yield this.git.tryConfigUnsetValue(key, value, false, configPath);
498+ }
499+ }
500+ }
501+ }
502+ }
503+ catch (err) {
504+ // Ignore errors - this is cleanup code
505+ core.debug(`Error during includeIf cleanup${configPath ? ` for ${configPath}` : ''}: ${err}`);
506+ }
507+ return Array.from(credentialsPaths);
508+ });
509+ }
510+ /**
511+ * Tests if a path matches the git-credentials-*.config pattern used by newer versions.
512+ * @param path The path to test
513+ * @returns True if the path matches the credentials config pattern
514+ */
515+ testCredentialsConfigPath(path) {
516+ return /git-credentials-[0-9a-f-]+\.config$/i.test(path);
517+ }
433518}
434519
435520
@@ -706,6 +791,16 @@ class GitCommandManager {
706791 throw new Error('Unexpected output when retrieving default branch');
707792 });
708793 }
794+ getSubmoduleConfigPaths(recursive) {
795+ return __awaiter(this, void 0, void 0, function* () {
796+ // Get submodule config file paths.
797+ // Use `--show-origin` to get the config file path for each submodule.
798+ const output = yield this.submoduleForeach(`git config --local --show-origin --name-only --get-regexp remote.origin.url`, recursive);
799+ // Extract config file paths from the output (lines starting with "file:").
800+ const configPaths = output.match(/(?<=(^|\n)file:)[^\t]+(?=\tremote\.origin\.url)/g) || [];
801+ return configPaths;
802+ });
803+ }
709804 getWorkingDirectory() {
710805 return this.workingDirectory;
711806 }
@@ -836,6 +931,20 @@ class GitCommandManager {
836931 return output.exitCode === 0;
837932 });
838933 }
934+ tryConfigUnsetValue(configKey, configValue, globalConfig, configFile) {
935+ return __awaiter(this, void 0, void 0, function* () {
936+ const args = ['config'];
937+ if (configFile) {
938+ args.push('--file', configFile);
939+ }
940+ else {
941+ args.push(globalConfig ? '--global' : '--local');
942+ }
943+ args.push('--unset', configKey, configValue);
944+ const output = yield this.execGit(args, true);
945+ return output.exitCode === 0;
946+ });
947+ }
839948 tryDisableAutomaticGarbageCollection() {
840949 return __awaiter(this, void 0, void 0, function* () {
841950 const output = yield this.execGit(['config', '--local', 'gc.auto', '0'], true);
@@ -855,6 +964,46 @@ class GitCommandManager {
855964 return stdout;
856965 });
857966 }
967+ tryGetConfigValues(configKey, globalConfig, configFile) {
968+ return __awaiter(this, void 0, void 0, function* () {
969+ const args = ['config'];
970+ if (configFile) {
971+ args.push('--file', configFile);
972+ }
973+ else {
974+ args.push(globalConfig ? '--global' : '--local');
975+ }
976+ args.push('--get-all', configKey);
977+ const output = yield this.execGit(args, true);
978+ if (output.exitCode !== 0) {
979+ return [];
980+ }
981+ return output.stdout
982+ .trim()
983+ .split('\n')
984+ .filter(value => value.trim());
985+ });
986+ }
987+ tryGetConfigKeys(pattern, globalConfig, configFile) {
988+ return __awaiter(this, void 0, void 0, function* () {
989+ const args = ['config'];
990+ if (configFile) {
991+ args.push('--file', configFile);
992+ }
993+ else {
994+ args.push(globalConfig ? '--global' : '--local');
995+ }
996+ args.push('--name-only', '--get-regexp', pattern);
997+ const output = yield this.execGit(args, true);
998+ if (output.exitCode !== 0) {
999+ return [];
1000+ }
1001+ return output.stdout
1002+ .trim()
1003+ .split('\n')
1004+ .filter(key => key.trim());
1005+ });
1006+ }
8581007 tryReset() {
8591008 return __awaiter(this, void 0, void 0, function* () {
8601009 const output = yield this.execGit(['reset', '--hard', 'HEAD'], true);
0 commit comments