From dcd4fb1eb3b271518585fe01d28cb0c32603c002 Mon Sep 17 00:00:00 2001 From: anamnavi Date: Fri, 29 Aug 2025 16:13:48 -0400 Subject: [PATCH 1/4] Add CodeQL suppressions for intended PowerShell behavior Round 2 --- .../commands/management/Process.cs | 1 + .../utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs | 1 + .../engine/NativeCommandProcessor.cs | 1 + .../engine/remoting/common/RunspaceConnectionInfo.cs | 1 + src/System.Management.Automation/help/UpdatableHelpSystem.cs | 2 ++ .../namespaces/FileSystemProvider.cs | 1 + 6 files changed, 7 insertions(+) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs index 56efe65b4bb..20ecaf6c5bc 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs @@ -1903,6 +1903,7 @@ protected override void BeginProcessing() } catch (CommandNotFoundException) { + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path they are specifying and the process is on the user's system except for remoting where they should use restricted remoting security guidelines. startInfo.FileName = FilePath; #if UNIX // Arguments are passed incorrectly to the executable used for ShellExecute and not to filename https://github.com/dotnet/corefx/issues/30718 diff --git a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs index 47895a88c09..df45f1307e4 100644 --- a/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs +++ b/src/Microsoft.PowerShell.Commands.Utility/commands/utility/WebCmdlet/Common/WebRequestPSCmdlet.Common.cs @@ -1298,6 +1298,7 @@ internal virtual HttpResponseMessage GetResponse(HttpClient client, HttpRequestM WriteDebug(reqDebugMsg); + // codeql[cs/ssrf] - This is expected Poweshell behavior where user inputted Uri is supported for the context of this method. The user assumes trust for the Uri and invocation is done on the user's machine, not a web application. If there is concern for remoting, they should use restricted remoting. response = client.SendAsync(currentRequest, HttpCompletionOption.ResponseHeadersRead, _cancelToken.Token).GetAwaiter().GetResult(); string contentType = ContentHelper.GetContentType(response); diff --git a/src/System.Management.Automation/engine/NativeCommandProcessor.cs b/src/System.Management.Automation/engine/NativeCommandProcessor.cs index 371e1ff00ff..56dadec38d2 100644 --- a/src/System.Management.Automation/engine/NativeCommandProcessor.cs +++ b/src/System.Management.Automation/engine/NativeCommandProcessor.cs @@ -1396,6 +1396,7 @@ private ProcessStartInfo GetProcessStartInfo( { var startInfo = new ProcessStartInfo { + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path specified to retrieved process info for, so any info would be for the user except for remoting in which case restricted remoting security guidelines should be used. FileName = this.Path }; diff --git a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs index 9c221f01dbb..d18eb249cb7 100644 --- a/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs +++ b/src/System.Management.Automation/engine/remoting/common/RunspaceConnectionInfo.cs @@ -2230,6 +2230,7 @@ internal int StartSSHProcess( // linux|macos: // Subsystem powershell /usr/local/bin/pwsh -SSHServerMode -NoLogo -NoProfile + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path specified, so any file executed in the runspace would be in the user's local system/process or a system they have access to in which case restricted remoting security guidelines should be used. System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo(filePath); // pass "-i identity_file" command line argument to ssh if KeyFilePath is set diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs index 6ab8d469a97..6594cdee20e 100644 --- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs +++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs @@ -419,6 +419,7 @@ private string ResolveUri(string baseUri, bool verbose) using (HttpClient client = new HttpClient(handler)) { client.Timeout = new TimeSpan(0, 0, 30); // Set 30 second timeout + // codeql[cs/ssrf] - This is expected Poweshell behavior and the user assumes the risk for the help content Uri they are invoking PowerShell for on their machine. PowerShell is not a web application or server, so no server side resources are at risk. Task responseMessage = client.GetAsync(uri); using (HttpResponseMessage response = responseMessage.Result) { @@ -783,6 +784,7 @@ private bool DownloadHelpContentHttpClient(string uri, string fileName, Updatabl using (HttpClient client = new HttpClient(handler)) { client.Timeout = _defaultTimeout; + // codeql[cs/ssrf] - This is expected Poweshell behavior where the user assumes the risk for the help content they download on their machine. PowerShell is not a web application or server, so no server side resources are at risk. Task responseMsg = client.GetAsync(new Uri(uri), _cancelTokenSource.Token); // TODO: Should I use a continuation to write the stream to a file? diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 3423709d3cf..101d6360676 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1324,6 +1324,7 @@ protected override void InvokeDefaultAction(string path) if (ShouldProcess(resource, action)) { var invokeProcess = new System.Diagnostics.Process(); + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path they are specifying. invokeProcess.StartInfo.FileName = path; #if UNIX bool useShellExecute = false; From be53be44ddbf0841ad1929f9012b2f309af13256 Mon Sep 17 00:00:00 2001 From: anamnavi Date: Fri, 29 Aug 2025 17:48:01 -0400 Subject: [PATCH 2/4] Update the suppression messages to sound more consistent --- .../engine/NativeCommandProcessor.cs | 2 +- src/System.Management.Automation/help/UpdatableHelpSystem.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/System.Management.Automation/engine/NativeCommandProcessor.cs b/src/System.Management.Automation/engine/NativeCommandProcessor.cs index 56dadec38d2..43113d07425 100644 --- a/src/System.Management.Automation/engine/NativeCommandProcessor.cs +++ b/src/System.Management.Automation/engine/NativeCommandProcessor.cs @@ -1396,7 +1396,7 @@ private ProcessStartInfo GetProcessStartInfo( { var startInfo = new ProcessStartInfo { - // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path specified to retrieved process info for, so any info would be for the user except for remoting in which case restricted remoting security guidelines should be used. + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path specified on the user's system to retrieve process info for, and in the case of remoting, restricted remoting security guidelines should be used. FileName = this.Path }; diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs index 6594cdee20e..84079bec1b7 100644 --- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs +++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs @@ -419,7 +419,7 @@ private string ResolveUri(string baseUri, bool verbose) using (HttpClient client = new HttpClient(handler)) { client.Timeout = new TimeSpan(0, 0, 30); // Set 30 second timeout - // codeql[cs/ssrf] - This is expected Poweshell behavior and the user assumes the risk for the help content Uri they are invoking PowerShell for on their machine. PowerShell is not a web application or server, so no server side resources are at risk. + // codeql[cs/ssrf] - This is expected Poweshell behavior and the user assumes trust for the Uri and invocation is done on the user's machine, as PowerShell is not a web application/server. If there is concern for remoting, restricted remoting guidelines should be used. Task responseMessage = client.GetAsync(uri); using (HttpResponseMessage response = responseMessage.Result) { @@ -784,7 +784,7 @@ private bool DownloadHelpContentHttpClient(string uri, string fileName, Updatabl using (HttpClient client = new HttpClient(handler)) { client.Timeout = _defaultTimeout; - // codeql[cs/ssrf] - This is expected Poweshell behavior where the user assumes the risk for the help content they download on their machine. PowerShell is not a web application or server, so no server side resources are at risk. + // codeql[cs/ssrf] - This is expected Poweshell behavior and the user assumes trust for the Uri of the help content they are downloading and invocation is done on the user's machine, as PowerShell is not a web application/server. If there is concern for remoting, restricted remoting guidelines should be used. Task responseMsg = client.GetAsync(new Uri(uri), _cancelTokenSource.Token); // TODO: Should I use a continuation to write the stream to a file? From 4578b9363e68c6290fb29e4f7fccb2f265c11b4b Mon Sep 17 00:00:00 2001 From: anamnavi Date: Fri, 29 Aug 2025 17:56:58 -0400 Subject: [PATCH 3/4] Update more suppression messages --- .../commands/management/Process.cs | 2 +- .../namespaces/FileSystemProvider.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs index 20ecaf6c5bc..2e07a945a00 100644 --- a/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs +++ b/src/Microsoft.PowerShell.Commands.Management/commands/management/Process.cs @@ -1903,7 +1903,7 @@ protected override void BeginProcessing() } catch (CommandNotFoundException) { - // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path they are specifying and the process is on the user's system except for remoting where they should use restricted remoting security guidelines. + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path they are specifying and the process is on the user's system except for remoting in which case restricted remoting security guidelines should be used. startInfo.FileName = FilePath; #if UNIX // Arguments are passed incorrectly to the executable used for ShellExecute and not to filename https://github.com/dotnet/corefx/issues/30718 diff --git a/src/System.Management.Automation/namespaces/FileSystemProvider.cs b/src/System.Management.Automation/namespaces/FileSystemProvider.cs index 101d6360676..30580efb17c 100644 --- a/src/System.Management.Automation/namespaces/FileSystemProvider.cs +++ b/src/System.Management.Automation/namespaces/FileSystemProvider.cs @@ -1324,7 +1324,7 @@ protected override void InvokeDefaultAction(string path) if (ShouldProcess(resource, action)) { var invokeProcess = new System.Diagnostics.Process(); - // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path they are specifying. + // codeql[cs/microsoft/command-line-injection-shell-execution] - This is expected Poweshell behavior where user inputted paths are supported for the context of this method. The user assumes trust for the file path they are specifying. If there is concern for remoting, restricted remoting guidelines should be used. invokeProcess.StartInfo.FileName = path; #if UNIX bool useShellExecute = false; From 335bcc5d8ef47e10c76619e533ef3a1ec824ec96 Mon Sep 17 00:00:00 2001 From: anamnavi Date: Fri, 29 Aug 2025 18:17:53 -0400 Subject: [PATCH 4/4] remove comments from UpdatableHelpSystem --- src/System.Management.Automation/help/UpdatableHelpSystem.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/System.Management.Automation/help/UpdatableHelpSystem.cs b/src/System.Management.Automation/help/UpdatableHelpSystem.cs index 84079bec1b7..6ab8d469a97 100644 --- a/src/System.Management.Automation/help/UpdatableHelpSystem.cs +++ b/src/System.Management.Automation/help/UpdatableHelpSystem.cs @@ -419,7 +419,6 @@ private string ResolveUri(string baseUri, bool verbose) using (HttpClient client = new HttpClient(handler)) { client.Timeout = new TimeSpan(0, 0, 30); // Set 30 second timeout - // codeql[cs/ssrf] - This is expected Poweshell behavior and the user assumes trust for the Uri and invocation is done on the user's machine, as PowerShell is not a web application/server. If there is concern for remoting, restricted remoting guidelines should be used. Task responseMessage = client.GetAsync(uri); using (HttpResponseMessage response = responseMessage.Result) { @@ -784,7 +783,6 @@ private bool DownloadHelpContentHttpClient(string uri, string fileName, Updatabl using (HttpClient client = new HttpClient(handler)) { client.Timeout = _defaultTimeout; - // codeql[cs/ssrf] - This is expected Poweshell behavior and the user assumes trust for the Uri of the help content they are downloading and invocation is done on the user's machine, as PowerShell is not a web application/server. If there is concern for remoting, restricted remoting guidelines should be used. Task responseMsg = client.GetAsync(new Uri(uri), _cancelTokenSource.Token); // TODO: Should I use a continuation to write the stream to a file?