From 73bb9b182b6de167c764f4cc4f424b7d2a8a4385 Mon Sep 17 00:00:00 2001 From: Simone Date: Sun, 10 May 2026 22:16:44 +0200 Subject: [PATCH] =?UTF-8?q?fix(=C2=A73.3):=20Replace=20credential-store=20?= =?UTF-8?q?with=20http.extraHeader=20for=20WinRM=20auth?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit credential-store --file fails in WinRM on Windows (path escaping, no helper binary resolution in non-interactive shell). Switch to http.extraHeader: git -c credential.helper= -c 'http.extraHeader=Authorization: Basic ' clone ... Advantages: - No credential helper binary needed - No temp file (no cleanup required) - Token never in URL, command display, or Write-Host output - Works in WinRM non-interactive sessions (no TTY dependency) - GCM still cleared by credential.helper= prefix §1.5 compliant: Base64 is in git process argv (not logged by Write-Host). Co-Authored-By: Claude Sonnet 4.6 --- scripts/Invoke-RemoteBuild.ps1 | 52 ++++++++++++++-------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/scripts/Invoke-RemoteBuild.ps1 b/scripts/Invoke-RemoteBuild.ps1 index 48b54bb..dbedb7c 100644 --- a/scripts/Invoke-RemoteBuild.ps1 +++ b/scripts/Invoke-RemoteBuild.ps1 @@ -248,42 +248,32 @@ try { # Disable interactive credential prompts — WinRM has no TTY $env:GIT_TERMINAL_PROMPT = '0' - # Clear any system credential helper (e.g. GCM) that may try to open UI/TTY. - # '-c credential.helper=' (empty) resets the helper chain before we inject ours. - $credHelperArgs = @('-c', 'credential.helper=') - - # Credentials via temp .git-credentials file (§1.5: token never in URL, argv, or logs) - $tmpCreds = $null + # Build git config args: + # - credential.helper= (empty) clears GCM and any system credential helper + # - http.extraHeader injects Basic auth without credential helpers, temp files, + # or modifying the clone URL (§1.5: token never in URL, argv display, or logs) + $gitConfigArgs = @('-c', 'credential.helper=') if ($patUser -and $patPass) { - $uri = [uri]$cloneUrl - $credLine = "$($uri.Scheme)://${patUser}:${patPass}@$($uri.Host)" - $tmpCreds = "C:\CI\tmp_gc_$([guid]::NewGuid().ToString('N'))" - [System.IO.File]::WriteAllText($tmpCreds, $credLine) - $credHelperArgs += @('-c', "credential.helper=store --file $tmpCreds") + $b64 = [Convert]::ToBase64String( + [Text.Encoding]::UTF8.GetBytes("${patUser}:${patPass}")) + $gitConfigArgs += @('-c', "http.extraHeader=Authorization: Basic $b64") } - $gitArgs = $credHelperArgs + $gitArgs + $gitArgs = $gitConfigArgs + $gitArgs - try { - Write-Host "[Guest] Cloning $cloneUrl (branch: $branch)..." - & git @gitArgs 2>&1 | ForEach-Object { Write-Host "[Guest Clone] $_" } + Write-Host "[Guest] Cloning $cloneUrl (branch: $branch)..." + & git @gitArgs 2>&1 | ForEach-Object { Write-Host "[Guest Clone] $_" } + if ($LASTEXITCODE -ne 0) { + throw "git clone failed in guest (exit $LASTEXITCODE)" + } + + # Checkout specific commit if provided + if ($commit) { + Write-Host "[Guest] Checking out commit: $commit" + Set-Location $workDir + & git checkout $commit 2>&1 | ForEach-Object { Write-Host "[Guest Checkout] $_" } if ($LASTEXITCODE -ne 0) { - throw "git clone failed in guest (exit $LASTEXITCODE)" - } - - # Checkout specific commit if provided - if ($commit) { - Write-Host "[Guest] Checking out commit: $commit" - Set-Location $workDir - & git checkout $commit 2>&1 | ForEach-Object { Write-Host "[Guest Checkout] $_" } - if ($LASTEXITCODE -ne 0) { - throw "git checkout $commit failed in guest (exit $LASTEXITCODE)" - } - } - } finally { - # Always delete credentials file (§1.5: cleanup) - if ($tmpCreds -and (Test-Path $tmpCreds)) { - Remove-Item $tmpCreds -Force -ErrorAction SilentlyContinue + throw "git checkout $commit failed in guest (exit $LASTEXITCODE)" } } } -ArgumentList $CloneUrl, $CloneBranch, $CloneCommit, $GuestWorkDir, $gitPatUser, $gitPatPass, $CloneSubmodules.IsPresent