From 633e31085d9b020304e98bc72c4d16112bd5d66c Mon Sep 17 00:00:00 2001 From: Vladyslav Horbachov Date: Tue, 3 Oct 2023 11:22:36 +0200 Subject: [PATCH] Updated regex to allow more characters Copy of https://github.com/microsoft/azure-pipelines-tasks/pull/19028 --- .../Sanitizer/ArgumentsSanitizer.ps1 | 4 +- .../resources.resjson/de-DE/resources.resjson | 2 + .../resources.resjson/en-US/resources.resjson | 2 +- .../resources.resjson/es-ES/resources.resjson | 2 + .../resources.resjson/fr-FR/resources.resjson | 2 + .../resources.resjson/it-IT/resources.resjson | 2 + .../resources.resjson/ja-JP/resources.resjson | 2 + .../resources.resjson/ko-KR/resources.resjson | 2 + .../resources.resjson/ru-RU/resources.resjson | 2 + .../resources.resjson/zh-CN/resources.resjson | 2 + .../resources.resjson/zh-TW/resources.resjson | 2 + TaskModules/powershell/Sanitizer/Tests/L0.ts | 19 ++++++--- ...sArray.DoesNotBreakExistingBashFormats.ps1 | 4 +- ...tsArray.DoesNotBreakExistingCmdFormats.ps1 | 2 +- ....DoesNotBreakExistingPowerShellFormats.ps1 | 2 +- ...mentsArray.ReplacesForbiddenCharacters.ps1 | 4 +- .../L0Protect-ScriptArguments.Passes.ps1 | 41 +++++++++++++++++++ .../L0Protect-ScriptArguments.Throws.ps1 | 22 ++++++++++ .../Sanitizer/Tests/L0Split-Arguments.ps1 | 4 +- TaskModules/powershell/Sanitizer/module.json | 2 +- 20 files changed, 106 insertions(+), 18 deletions(-) create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/de-DE/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/es-ES/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/fr-FR/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/it-IT/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/ja-JP/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/ko-KR/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/ru-RU/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-CN/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-TW/resources.resjson create mode 100644 TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Passes.ps1 create mode 100644 TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Throws.ps1 diff --git a/TaskModules/powershell/Sanitizer/ArgumentsSanitizer.ps1 b/TaskModules/powershell/Sanitizer/ArgumentsSanitizer.ps1 index b24c43d8a..160e1a2c1 100644 --- a/TaskModules/powershell/Sanitizer/ArgumentsSanitizer.ps1 +++ b/TaskModules/powershell/Sanitizer/ArgumentsSanitizer.ps1 @@ -60,7 +60,7 @@ function Get-SanitizedArguments([string]$inputArgs) { # regex rule for removing symbols and telemetry. # '?", + "loc.messages.PS_ScriptArgsSanitized": "Detected characters in arguments that may not be executed correctly by the shell. Please escape special characters using backtick (`). More information is available here: https://aka.ms/ado/75787", "loc.messages.PS_ScriptArgsNotSanitized": "Arguments passed sanitization without change." } \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/es-ES/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/es-ES/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/es-ES/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/fr-FR/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/fr-FR/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/fr-FR/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/it-IT/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/it-IT/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/it-IT/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ja-JP/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ja-JP/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ja-JP/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ko-KR/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ko-KR/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ko-KR/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ru-RU/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ru-RU/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/ru-RU/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-CN/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-CN/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-CN/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-TW/resources.resjson b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-TW/resources.resjson new file mode 100644 index 000000000..7a73a41bf --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Strings/resources.resjson/zh-TW/resources.resjson @@ -0,0 +1,2 @@ +{ +} \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Tests/L0.ts b/TaskModules/powershell/Sanitizer/Tests/L0.ts index 194fdf836..a770c8468 100644 --- a/TaskModules/powershell/Sanitizer/Tests/L0.ts +++ b/TaskModules/powershell/Sanitizer/Tests/L0.ts @@ -1,12 +1,9 @@ /// /// -/// -import Q = require('q'); -import assert = require('assert'); import path = require('path'); -var psm = require('../../../Tests/lib/psRunner'); +var psm = require('../../../../Tests/lib/psRunner'); var psr = null; describe('Security Suite', function () { @@ -49,4 +46,16 @@ describe('Security Suite', function () { psr.run(path.join(__dirname, 'L0Get-SanitizedArgumentsArray.DoesNotBreakExistingBashFormats.ps1'), done); }); } -}); \ No newline at end of file + + if (psm.testSupported()) { + it('Protect-ScriptArguments should pass correctly', (done) => { + psr.run(path.join(__dirname, 'L0Protect-ScriptArguments.Passes.ps1'), done); + }); + } + + if (psm.testSupported()) { + it('Protect-ScriptArguments should throw', (done) => { + psr.run(path.join(__dirname, 'L0Protect-ScriptArguments.Throws.ps1'), done); + }); + } +}); diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingBashFormats.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingBashFormats.ps1 index 01af752bc..76bdd2bd0 100644 --- a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingBashFormats.ps1 +++ b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingBashFormats.ps1 @@ -21,5 +21,5 @@ foreach ($argument in $bashArgumentsFormats) { $sanitizedArguments = Get-SanitizedArguments -InputArgs $argument # Assert - Assert-AreEqual $sanitizedArguments $argument -} \ No newline at end of file + Assert-AreEqual -Actual $sanitizedArguments -Expected $argument +} diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingCmdFormats.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingCmdFormats.ps1 index 070d9568a..5ff8bccec 100644 --- a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingCmdFormats.ps1 +++ b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingCmdFormats.ps1 @@ -20,5 +20,5 @@ foreach ($argument in $cmdArgumentsFormats) { $sanitizedArguments = Get-SanitizedArguments -InputArgs $argument # Assert - Assert-AreEqual $sanitizedArguments $argument + Assert-AreEqual -Actual $sanitizedArguments -Expected $argument } \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingPowerShellFormats.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingPowerShellFormats.ps1 index 22cdef700..5c7f2a783 100644 --- a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingPowerShellFormats.ps1 +++ b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.DoesNotBreakExistingPowerShellFormats.ps1 @@ -21,5 +21,5 @@ foreach ($argument in $powershellArgumentsFormats) { $sanitizedArguments = Get-SanitizedArguments -InputArgs $argument # Assert - Assert-AreEqual $sanitizedArguments $argument + Assert-AreEqual -Actual $sanitizedArguments -Expected $argument } \ No newline at end of file diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.ReplacesForbiddenCharacters.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.ReplacesForbiddenCharacters.ps1 index a71fe62af..214311c89 100644 --- a/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.ReplacesForbiddenCharacters.ps1 +++ b/TaskModules/powershell/Sanitizer/Tests/L0Get-SanitizedArgumentsArray.ReplacesForbiddenCharacters.ps1 @@ -14,5 +14,5 @@ $sanitizedArguments = Get-SanitizedArguments -InputArgs $arguments # Assert -# We need to use $sanitizedArguments[1] because $sanitizedArguments contains buffer with Write-Output message from the function execution. -Assert-AreEqual $sanitizedArguments[1] "start notepad.exe _#removed#_ echo 'hello' _#removed#_ calc.exe" \ No newline at end of file +# We need to use $sanitizedArguments[1] because $sanitizedArguments contains buffer with Write-Output message from the function execution. +Assert-AreEqual -Expected "start notepad.exe _#removed#_ echo 'hello' _#removed#_ calc.exe" -Actual $sanitizedArguments diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Passes.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Passes.ps1 new file mode 100644 index 000000000..a81e6c9d6 --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Passes.ps1 @@ -0,0 +1,41 @@ +[CmdletBinding()] +param() + +Set-Item -Path env:AZP_75787_ENABLE_NEW_LOGIC -Value 'true' + +. $PSScriptRoot\..\..\..\..\Tests\lib\Initialize-Test.ps1 +. $PSScriptRoot\..\ArgumentsSanitizer.ps1 + +$inputArgsSuites = @( + "/parameter", # Traditional way to pass parameters in CMD + "-parameter", # Modern applications accept parameters with a hyphen + "--parameter", # Many modern applications accept parameters with double hyphen + "parameter=value", # Format for passing values to parameters + "parameter value.txt", # Argument with dot in the middle + "-parameter", # Single hyphen followed by a single letter or digit (POSIX style) + "-parameter value", # When the parameter needs a value + "--parameter", # Double hyphen followed by a word (GNU style) + "--parameter=value", # Value directly attached to the parameter with an equals sign + "parameter=value", # Used to pass environment variables to a command + "parameter value.txt", # Argument with dot in the middle + "-Parameter Value", # Most common form + "-Parameter:Value", # Colon connects the parameter and its value + "/p:Parameter=Value", # Specific syntax for tools like MSBuild or NuGet + "--Parameter Value", # Used by cmdlets or scripts for cross-platform compatibility + "--Parameter=Value", # Used by cross-platform tools + "parameter value.txt" # Argument with dot in the middle + 'a A 1 \ ` _ '' " - = / : . * , + ~ ? %', # Just each allowed symbol + '', + 'test 1', + 'test `; whoami `&`& echo test', + "line 1 `n line 2" +) + +foreach ($inputArgs in $inputArgsSuites) { + try { + Protect-ScriptArguments $inputArgs + } + catch { + throw "Error occured with '$inputArgs' input args: $($_.Exception.Message)" + } +} diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Throws.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Throws.ps1 new file mode 100644 index 000000000..2b8f65262 --- /dev/null +++ b/TaskModules/powershell/Sanitizer/Tests/L0Protect-ScriptArguments.Throws.ps1 @@ -0,0 +1,22 @@ +[CmdletBinding()] +param() + +Set-Item -Path env:AZP_75787_ENABLE_NEW_LOGIC -Value 'true' + +. $PSScriptRoot\..\..\..\..\Tests\lib\Initialize-Test.ps1 +. $PSScriptRoot\..\ArgumentsSanitizer.ps1 + +$inputArgsSuites = @( + 'test; whoami', + 'test && whoami', + 'echo "$(rm ./somedir)"', + 'test | whoami' +) + +$expectedMsg = Get-VstsLocString -Key 'PS_ScriptArgsSanitized' + +foreach ($inputArgs in $inputArgsSuites) { + Assert-Throws { + Protect-ScriptArguments $inputArgs + } -MessagePattern $expectedMsg +} diff --git a/TaskModules/powershell/Sanitizer/Tests/L0Split-Arguments.ps1 b/TaskModules/powershell/Sanitizer/Tests/L0Split-Arguments.ps1 index 3a4f82905..9a4f45a7d 100644 --- a/TaskModules/powershell/Sanitizer/Tests/L0Split-Arguments.ps1 +++ b/TaskModules/powershell/Sanitizer/Tests/L0Split-Arguments.ps1 @@ -33,5 +33,5 @@ for ($i = 0; $i -lt $argumentsFormats.Length; $i++) { [string[]]$splitArguments = Split-Arguments -arguments $argumentsFormats[$i] # Assert - Assert-AreEqual $splitArguments $expectedOutputs[$i] -} \ No newline at end of file + Assert-AreEqual -Expected $splitArguments -Actual $expectedOutputs[$i] +} diff --git a/TaskModules/powershell/Sanitizer/module.json b/TaskModules/powershell/Sanitizer/module.json index b00eb9eb7..52d6c692b 100644 --- a/TaskModules/powershell/Sanitizer/module.json +++ b/TaskModules/powershell/Sanitizer/module.json @@ -1,6 +1,6 @@ { "messages": { - "PS_ScriptArgsSanitized": "Detected characters in arguments that may not be executed correctly by the shell. Please escape special characters using backtick (`). More information is available here: ", + "PS_ScriptArgsSanitized": "Detected characters in arguments that may not be executed correctly by the shell. Please escape special characters using backtick (`). More information is available here: https://aka.ms/ado/75787", "PS_ScriptArgsNotSanitized": "Arguments passed sanitization without change." } } \ No newline at end of file