Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -592,12 +592,20 @@ protected override void ProcessRecord()
OutFile = null;
}

// Detect insecure redirection
if (!AllowInsecureRedirect && response.RequestMessage.RequestUri.Scheme == "https" && response.Headers.Location?.Scheme == "http")
// Detect insecure redirection.
if (!AllowInsecureRedirect)
{
ErrorRecord er = new(new InvalidOperationException(), "InsecureRedirection", ErrorCategory.InvalidOperation, request);
er.ErrorDetails = new ErrorDetails(WebCmdletStrings.InsecureRedirection);
ThrowTerminatingError(er);
// We will skip detection if either of the URIs is relative, because the 'Scheme' property is not supported on a relative URI.
// If we have to skip the check, an error may be thrown later if it's actually an insecure https-to-http redirect.
bool originIsHttps = response.RequestMessage.RequestUri.IsAbsoluteUri && response.RequestMessage.RequestUri.Scheme == "https";
bool destinationIsHttp = response.Headers.Location is not null && response.Headers.Location.IsAbsoluteUri && response.Headers.Location.Scheme == "http";

if (originIsHttps && destinationIsHttp)
{
ErrorRecord er = new(new InvalidOperationException(), "InsecureRedirection", ErrorCategory.InvalidOperation, request);
er.ErrorDetails = new ErrorDetails(WebCmdletStrings.InsecureRedirection);
ThrowTerminatingError(er);
}
}

if (ShouldCheckHttpStatus && !_isSuccess)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1149,6 +1149,15 @@ Describe "Invoke-WebRequest tests" -Tags "Feature", "RequireAdminOnWindows" {
$result = ExecuteWebCommand -command $command
$result.Error.FullyQualifiedErrorId | Should -Be "InsecureRedirection,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
}

It "Validate Invoke-WebRequest Https to Http (No Scheme) redirect without -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @{destination = $httpUri.Authority}
$command = "Invoke-WebRequest -Uri '$uri' -SkipCertificateCheck"

$result = ExecuteWebCommand -command $command
$result.Error.FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before the fix was it "InsecureRedirection" exception? Could you please explain why now it is WebCmdletWebResponseException?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I introduced "InsecureRedirection" exception in #18595, previously it was WebCmdletWebResponseException.
If the uri has no scheme checking for a scheme would throw an error, so we skip the check and we go back to the old error on https to http redirection

}
}


Expand Down Expand Up @@ -3100,6 +3109,15 @@ Describe "Invoke-RestMethod tests" -Tags "Feature", "RequireAdminOnWindows" {
$result.Error.FullyQualifiedErrorId | Should -Be "InsecureRedirection,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}

It "Validate Invoke-RestMethod Https to Http (No Scheme) redirect without -AllowInsecureRedirect" {
$httpUri = Get-WebListenerUrl -Test 'Get'
$uri = Get-WebListenerUrl -Test 'Redirect' -Https -Query @{destination = $httpUri.Authority}
$command = "Invoke-RestMethod -Uri '$uri' -SkipCertificateCheck"

$result = ExecuteWebCommand -command $command
$result.Error.FullyQualifiedErrorId | Should -Be "WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeRestMethodCommand"
}

#endregion Redirect tests

Context "Invoke-RestMethod SkipHeaderVerification Tests" {
Expand Down