# Agent-safe: decrypt the local token and feed it to Git Credential Manager. # Never prints the token. Never writes it to a file. param( [Parameter(Mandatory = $true)] [string]$RemoteUrl ) $ErrorActionPreference = 'Stop' . (Join-Path $PSScriptRoot 'common.ps1') $gitProfile = Get-GitSkillsProfile if ($null -eq $gitProfile) { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'profile_missing' exit 1 } $username = ([string]$gitProfile.gitUsername).Trim() if ([string]::IsNullOrWhiteSpace($username)) { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'git_username_missing' exit 1 } if ($username -match "[\r\n]") { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'git_username_invalid' exit 1 } if (-not (Test-Path -LiteralPath $script:TokenPath)) { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'token_missing' exit 1 } $parsed = Parse-GitRemoteUrl -RemoteUrl $RemoteUrl $hostName = [string]$parsed.CredentialHost if ([string]::IsNullOrWhiteSpace($hostName)) { $hostName = [string]$parsed.Host } if ([string]::IsNullOrWhiteSpace($hostName)) { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'host_parse_failed' exit 1 } $credProtocol = 'https' if ([string]$parsed.Protocol -eq 'http') { $credProtocol = 'http' } $token = $null $payload = $null try { $data = [System.IO.File]::ReadAllBytes($script:TokenPath) $token = Unprotect-SecretBytes -Data $data if ([string]::IsNullOrWhiteSpace($token)) { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'token_invalid' exit 1 } $payload = @" protocol=$credProtocol host=$hostName username=$username password=$token "@ $psi = New-Object System.Diagnostics.ProcessStartInfo $psi.FileName = 'git' $psi.Arguments = 'credential approve' $psi.UseShellExecute = $false $psi.RedirectStandardInput = $true $psi.RedirectStandardOutput = $true $psi.RedirectStandardError = $true $psi.CreateNoWindow = $true $proc = New-Object System.Diagnostics.Process $proc.StartInfo = $psi [void]$proc.Start() foreach ($line in ($payload -split "`r?`n")) { $proc.StandardInput.WriteLine($line) } $proc.StandardInput.Close() $null = $proc.StandardOutput.ReadToEnd() $null = $proc.StandardError.ReadToEnd() $proc.WaitForExit() if ($proc.ExitCode -ne 0) { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'git_credential_approve_failed' exit 1 } } catch { Write-StatusLine -Key 'status' -Value 'failed' Write-StatusLine -Key 'reason' -Value 'inject_error' exit 1 } finally { $token = $null $payload = $null $data = $null } Write-StatusLine -Key 'status' -Value 'injected' Write-StatusLine -Key 'host' -Value $hostName Write-StatusLine -Key 'protocol' -Value $credProtocol Write-StatusLine -Key 'username' -Value $username Write-Output 'token=hidden'