Skip to content

Commit cfe0f99

Browse files
Merged PR 28411: Redact Auth header content from ErrorRecord
Redact Auth header content from ErrorRecord
1 parent ccee763 commit cfe0f99

File tree

2 files changed

+50
-3
lines changed

2 files changed

+50
-3
lines changed

src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -836,6 +836,27 @@ private string GetBearerAuthorizationHeader()
836836
return string.Format("Bearer {0}", new NetworkCredential(string.Empty, Token).Password);
837837
}
838838

839+
private static HttpRequestMessage RedactAuthorizationHeader(HttpRequestMessage request)
840+
{
841+
if (request.Headers is not null && request.Headers.Authorization is not null && request.Headers.Authorization.Parameter is not null)
842+
{
843+
// redact the auth parameter, but leave the last 4 characters for developers to validate
844+
// the right token was sent
845+
var authParameter = request.Headers.Authorization.Parameter;
846+
var redactLength = authParameter.Length - 4;
847+
if (redactLength < 0)
848+
{
849+
redactLength = authParameter.Length;
850+
}
851+
852+
request.Headers.Authorization = new AuthenticationHeaderValue(
853+
request.Headers.Authorization.Scheme,
854+
string.Concat("****", authParameter.Substring(redactLength).AsSpan()));
855+
}
856+
857+
return request;
858+
}
859+
839860
private void ProcessAuthentication()
840861
{
841862
if (Authentication == WebAuthenticationType.Basic)
@@ -1546,7 +1567,7 @@ protected override void ProcessRecord()
15461567
string message = string.Format(CultureInfo.CurrentCulture, WebCmdletStrings.ResponseStatusCodeFailure,
15471568
(int)response.StatusCode, response.ReasonPhrase);
15481569
HttpResponseException httpEx = new(message, response);
1549-
ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request);
1570+
ErrorRecord er = new(httpEx, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request));
15501571
string detailMsg = string.Empty;
15511572
StreamReader reader = null;
15521573
try
@@ -1593,15 +1614,15 @@ protected override void ProcessRecord()
15931614
response.StatusCode == HttpStatusCode.Moved ||
15941615
response.StatusCode == HttpStatusCode.MovedPermanently)
15951616
{
1596-
ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, request);
1617+
ErrorRecord er = new(new InvalidOperationException(), "MaximumRedirectExceeded", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request));
15971618
er.ErrorDetails = new ErrorDetails(WebCmdletStrings.MaximumRedirectionCountExceeded);
15981619
WriteError(er);
15991620
}
16001621
}
16011622
}
16021623
catch (HttpRequestException ex)
16031624
{
1604-
ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, request);
1625+
ErrorRecord er = new(ex, "WebCmdletWebResponseException", ErrorCategory.InvalidOperation, RedactAuthorizationHeader(request));
16051626
if (ex.InnerException != null)
16061627
{
16071628
er.ErrorDetails = new ErrorDetails(ex.InnerException.Message);

test/powershell/Modules/Microsoft.PowerShell.Utility/WebCmdlets.Tests.ps1

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,6 +1706,19 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
17061706

17071707
$result.Headers.Authorization | Should -Match "^$AuthType "
17081708
}
1709+
1710+
It 'Invoke-WebRequest redacts Authorization header in ErrorRecord' {
1711+
$token = ConvertTo-SecureString -AsPlainText 'secret'
1712+
try {
1713+
Invoke-WebRequest -Authentication Bearer -Token $token -Uri https://localhost:443
1714+
}
1715+
catch {
1716+
$errorText = Get-Error $_ | Out-String
1717+
}
1718+
1719+
($errorText | Select-String 'secret').Matches | Should -BeNullOrEmpty
1720+
($errorText | Select-String '\*cret').Matches | Should -Not -BeNullOrEmpty
1721+
}
17091722
}
17101723

17111724
Context "Invoke-WebRequest -SslProtocol Test" {
@@ -3197,6 +3210,19 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
31973210

31983211
$result.Headers.Authorization | Should -Match "^$AuthType "
31993212
}
3213+
3214+
It 'Invoke-RestMethod redacts Authorization header in ErrorRecord' {
3215+
$token = ConvertTo-SecureString -AsPlainText 'secret'
3216+
try {
3217+
Invoke-RestMethod -Authentication Bearer -Token $token -Uri https://localhost:443
3218+
}
3219+
catch {
3220+
$errorText = Get-Error $_ | Out-String
3221+
}
3222+
3223+
($errorText | Select-String 'secret').Matches | Should -BeNullOrEmpty
3224+
($errorText | Select-String '\*cret').Matches | Should -Not -BeNullOrEmpty
3225+
}
32003226
}
32013227

32023228
Context "Invoke-RestMethod -SslProtocol Test" {

0 commit comments

Comments
 (0)