Merged PR 28409: Remove Auth header content from ErrorRecord

Remove Auth header content from ErrorRecord
This commit is contained in:
Aditya Patwardhan
2023-11-09 03:08:28 +00:00
parent cb14b1ba9a
commit 594abae9a1
2 changed files with 50 additions and 3 deletions
@@ -634,7 +634,7 @@ namespace Microsoft.PowerShell.Commands
response.ReasonPhrase);
HttpResponseException httpEx = new(message, response);
ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request);
ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request));
string detailMsg = string.Empty;
try
{
@@ -675,7 +675,7 @@ namespace Microsoft.PowerShell.Commands
// (and still writing out the result), users can debug actual HTTP redirect problems.
if (_maximumRedirection == 0 && IsRedirectCode(response.StatusCode))
{
ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request);
ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request));
er.ErrorDetails = new ErrorDetails(WebCmdletStrings.MaximumRedirectionCountExceeded);
WriteError(er);
}
@@ -687,7 +687,7 @@ namespace Microsoft.PowerShell.Commands
}
catch (HttpRequestException ex)
{
ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request);
ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request));
if (ex.InnerException is not null)
{
er.ErrorDetails = new ErrorDetails(ex.InnerException.Message);
@@ -1525,6 +1525,27 @@ namespace Microsoft.PowerShell.Commands
return string.Create(CultureInfo.InvariantCulture, $"Bearer {new NetworkCredential(string.Empty, Token).Password}");
}
private static HttpRequestMessage RedactAuthorizationHeader(HttpRequestMessage request)
{
if (request.Headers is not null && request.Headers.Authorization is not null && request.Headers.Authorization.Parameter is not null)
{
// redact the auth parameter, but leave the last 4 characters for developers to validate
// the right token was sent
var authParameter = request.Headers.Authorization.Parameter;
var redactLength = authParameter.Length - 4;
if (redactLength < 0)
{
redactLength = authParameter.Length;
}
request.Headers.Authorization = new AuthenticationHeaderValue(
request.Headers.Authorization.Scheme,
string.Concat("****", authParameter.Substring(redactLength).AsSpan()));
}
return request;
}
private void ProcessAuthentication()
{
if (Authentication == WebAuthenticationType.Basic)
@@ -1966,6 +1966,19 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
$result.Headers.Authorization | Should -Match "^$AuthType "
}
It 'Invoke-WebRequest redacts Authorization header in ErrorRecord' {
$token = ConvertTo-SecureString -AsPlainText 'secret'
try {
Invoke-WebRequest -Authentication Bearer -Token $token -Uri https://localhost:443
}
catch {
$errorText = Get-Error $_ | Out-String
}
($errorText | Select-String 'secret').Matches | Should -BeNullOrEmpty
($errorText | Select-String '\*cret').Matches | Should -Not -BeNullOrEmpty
}
}
Context "Invoke-WebRequest -SslProtocol Test" {
@@ -3922,6 +3935,19 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
$result.Headers.Authorization | Should -Match "^$AuthType "
}
It 'Invoke-RestMethod redacts Authorization header in ErrorRecord' {
$token = ConvertTo-SecureString -AsPlainText 'secret'
try {
Invoke-RestMethod -Authentication Bearer -Token $token -Uri https://localhost:443
}
catch {
$errorText = Get-Error $_ | Out-String
}
($errorText | Select-String 'secret').Matches | Should -BeNullOrEmpty
($errorText | Select-String '\*cret').Matches | Should -Not -BeNullOrEmpty
}
}
Context "Invoke-RestMethod -SslProtocol Test" {