From 6a88be69558834409269219991150a62ea27c4e7 Mon Sep 17 00:00:00 2001
From: Vladyslav Horbachov <50652041+LeftTwixWand@users.noreply.github.com>
Date: Tue, 3 Oct 2023 15:54:36 +0200
Subject: [PATCH] Update powershell sanitizer regex (#1199)
* Updated regex to allow more characters
Copy of https://github.com/microsoft/azure-pipelines-tasks/pull/19028
* Bump extension and tasks versions
---
.../IISWebAppDeployV1/task.json | 2 +-
.../IISWebAppDeployV2/task.json | 2 +-
.../IISWebAppMgmt/IISWebAppMgmtV1/task.json | 2 +-
.../IISWebAppMgmt/IISWebAppMgmtV2/task.json | 2 +-
.../IISWebAppMgmt/IISWebAppMgmtV3/task.json | 2 +-
.../SqlDacpacDeployV1/task.json | 2 +-
.../SqlDacpacDeployV2/task.json | 2 +-
.../IISWebAppDeploy/Src/vss-extension.json | 2 +-
.../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 +-
28 files changed, 114 insertions(+), 26 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/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV1/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV1/task.json
index c918165e9..9edd4abe2 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV1/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV1/task.json
@@ -7,7 +7,7 @@
"version": {
"Major": 1,
"Minor": 5,
- "Patch": 5
+ "Patch": 6
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV2/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV2/task.json
index ad08f4488..091b0f490 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV2/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppDeploy/IISWebAppDeployV2/task.json
@@ -16,7 +16,7 @@
"version": {
"Major": 2,
"Minor": 1,
- "Patch": 5
+ "Patch": 6
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV1/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV1/task.json
index 91d171051..f3b00c899 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV1/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV1/task.json
@@ -16,7 +16,7 @@
"version": {
"Major": 1,
"Minor": 4,
- "Patch": 5
+ "Patch": 6
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV2/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV2/task.json
index c2454b09b..fcb3e5fee 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV2/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV2/task.json
@@ -16,7 +16,7 @@
"version": {
"Major": 2,
"Minor": 2,
- "Patch": 5
+ "Patch": 6
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV3/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV3/task.json
index 899895117..b8101f697 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV3/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/IISWebAppMgmt/IISWebAppMgmtV3/task.json
@@ -16,7 +16,7 @@
"version": {
"Major": 3,
"Minor": 1,
- "Patch": 5
+ "Patch": 6
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV1/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV1/task.json
index 65b84b639..aa07a6d8b 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV1/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV1/task.json
@@ -16,7 +16,7 @@
"version": {
"Major": 1,
"Minor": 4,
- "Patch": 6
+ "Patch": 7
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV2/task.json b/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV2/task.json
index 442dabeca..0810902eb 100644
--- a/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV2/task.json
+++ b/Extensions/IISWebAppDeploy/Src/Tasks/SqlDacpacDeploy/SqlDacpacDeployV2/task.json
@@ -16,7 +16,7 @@
"version": {
"Major": 2,
"Minor": 1,
- "Patch": 6
+ "Patch": 7
},
"demands": [
],
diff --git a/Extensions/IISWebAppDeploy/Src/vss-extension.json b/Extensions/IISWebAppDeploy/Src/vss-extension.json
index 4ff4af397..e8bda2c78 100644
--- a/Extensions/IISWebAppDeploy/Src/vss-extension.json
+++ b/Extensions/IISWebAppDeploy/Src/vss-extension.json
@@ -2,7 +2,7 @@
"manifestVersion": 1,
"extensionId": "iiswebapp",
"name": "IIS Web App Deployment Using WinRM",
- "version": "1.6.7",
+ "version": "1.6.8",
"publisher": "ms-vscs-rm",
"description": "Using WinRM connect to the host Computer, to deploy a Web project using Web Deploy or a SQL DB using sqlpackage.exe.",
"public": true,
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