From 35f8d762118259837d8e870e1d568acc29af0e4f Mon Sep 17 00:00:00 2001 From: ArmaanMcleod Date: Sat, 15 Jul 2023 22:47:25 +1000 Subject: [PATCH 1/4] Added initial code to remove value from invalid secure string cast --- .../engine/LanguagePrimitives.cs | 22 +++++++++++++++++-- .../resources/ExtendedTypeSystem.resx | 3 +++ .../SecureString.Tests.ps1 | 14 ++++++++++++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index 9979d7433e5..e9b52a7fb95 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -21,6 +21,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Xml; +using System.Security; using Dbg = System.Management.Automation.Diagnostics; using MethodCacheEntry = System.Management.Automation.DotNetAdapter.MethodCacheEntry; @@ -4918,8 +4919,25 @@ internal static Tuple GetInvalidCastMessages(object valueToConve typeConversion.WriteLine("Type Conversion failed."); errorId = "ConvertToFinalInvalidCastException"; - errorMsg = StringUtil.Format(ExtendedTypeSystem.InvalidCastException, valueToConvert.ToString(), - ObjectToTypeNameString(valueToConvert), resultType.ToString()); + + string valueToConvertTypeName = ObjectToTypeNameString(valueToConvert); + string resultTypeName = resultType.ToString(); + + if (resultType == typeof(SecureString)) { + errorMsg = StringUtil.Format( + ExtendedTypeSystem.InvalidCastExceptionWithoutValue, + valueToConvertTypeName, + resultTypeName); + } + else + { + errorMsg = StringUtil.Format( + ExtendedTypeSystem.InvalidCastException, + valueToConvert.ToString(), + valueToConvertTypeName, + resultTypeName); + } + return Tuple.Create(errorId, errorMsg); } diff --git a/src/System.Management.Automation/resources/ExtendedTypeSystem.resx b/src/System.Management.Automation/resources/ExtendedTypeSystem.resx index 195fdbb7a1b..f8f9ca714cb 100644 --- a/src/System.Management.Automation/resources/ExtendedTypeSystem.resx +++ b/src/System.Management.Automation/resources/ExtendedTypeSystem.resx @@ -189,6 +189,9 @@ Cannot convert the "{0}" value of type "{1}" to type "{2}". + + Cannot convert the value of type "{0}" to type "{1}". + Cannot convert value "{0}" to type "{1}". Error: "{2}" diff --git a/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 index df1fa9294e1..3ae03cf7cd1 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 @@ -41,4 +41,18 @@ Describe "SecureString conversion tests" -Tags "CI" { $ss2 = $encodedStr | ConvertTo-SecureString -Key $key $ss2 | ConvertFrom-SecureString -AsPlainText | Should -BeExactly $testString } + + It "Using invalid secure string with ConvertFrom-SecureString produces an exception message without value" { + { ConvertFrom-SecureString "1234" } | + Should -Throw ` + -ErrorId "CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand" ` + -ExpectedMessage 'Cannot bind parameter ''SecureString''. Cannot convert the value of type "System.String" to type "System.Security.SecureString".' + } + + It "Using invalid securestring with cast produces an exception message without value" { + { [securestring]"1234" } | + Should -Throw ` + -ErrorId "ConvertToFinalInvalidCastException" ` + -ExpectedMessage 'Cannot convert the value of type "System.String" to type "System.Security.SecureString".' + } } From 9aa09b2dcfa742118fbff2e445dccb6cf2b1e7fc Mon Sep 17 00:00:00 2001 From: ArmaanMcleod Date: Sat, 15 Jul 2023 23:05:38 +1000 Subject: [PATCH 2/4] Fix formatting --- .../engine/LanguagePrimitives.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index e9b52a7fb95..3b164f457ed 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -4923,13 +4923,14 @@ internal static Tuple GetInvalidCastMessages(object valueToConve string valueToConvertTypeName = ObjectToTypeNameString(valueToConvert); string resultTypeName = resultType.ToString(); - if (resultType == typeof(SecureString)) { + if (resultType == typeof(SecureString)) + { errorMsg = StringUtil.Format( ExtendedTypeSystem.InvalidCastExceptionWithoutValue, valueToConvertTypeName, resultTypeName); } - else + else { errorMsg = StringUtil.Format( ExtendedTypeSystem.InvalidCastException, From 4d8d68c345bac672a837d0e307b866c810b86625 Mon Sep 17 00:00:00 2001 From: ArmaanMcleod Date: Sun, 16 Jul 2023 10:17:30 +1000 Subject: [PATCH 3/4] Add PSCredential support --- .../engine/LanguagePrimitives.cs | 2 +- test/powershell/engine/Basic/Credential.Tests.ps1 | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/LanguagePrimitives.cs b/src/System.Management.Automation/engine/LanguagePrimitives.cs index 3b164f457ed..ac78e5e80d5 100644 --- a/src/System.Management.Automation/engine/LanguagePrimitives.cs +++ b/src/System.Management.Automation/engine/LanguagePrimitives.cs @@ -4923,7 +4923,7 @@ internal static Tuple GetInvalidCastMessages(object valueToConve string valueToConvertTypeName = ObjectToTypeNameString(valueToConvert); string resultTypeName = resultType.ToString(); - if (resultType == typeof(SecureString)) + if (resultType == typeof(SecureString) || resultType == typeof(PSCredential)) { errorMsg = StringUtil.Format( ExtendedTypeSystem.InvalidCastExceptionWithoutValue, diff --git a/test/powershell/engine/Basic/Credential.Tests.ps1 b/test/powershell/engine/Basic/Credential.Tests.ps1 index eeccb18879f..9d7e4c8da24 100644 --- a/test/powershell/engine/Basic/Credential.Tests.ps1 +++ b/test/powershell/engine/Basic/Credential.Tests.ps1 @@ -5,4 +5,11 @@ Describe "Credential tests" -Tags "CI" { # We should explicitly check that the expression returns $null [PSCredential]::Empty.GetNetworkCredential() | Should -BeNullOrEmpty } + + It "Explicit credential cast with string produces an exception message without value" { + { [pscredential]"1234" } | + Should -Throw ` + -ErrorId "ConvertToFinalInvalidCastException" ` + -ExpectedMessage 'Cannot convert the value of type "System.String" to type "System.Management.Automation.PSCredential".' + } } From 60189340a533752d582956b354d5ca1caea3ffa9 Mon Sep 17 00:00:00 2001 From: ArmaanMcleod Date: Mon, 17 Jul 2023 20:22:47 +1000 Subject: [PATCH 4/4] Use explicit check of value in exception message --- .../SecureString.Tests.ps1 | 12 ++++-------- test/powershell/engine/Basic/Credential.Tests.ps1 | 6 ++---- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 b/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 index 3ae03cf7cd1..c26689cb7e9 100644 --- a/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 +++ b/test/powershell/Modules/Microsoft.PowerShell.Security/SecureString.Tests.ps1 @@ -43,16 +43,12 @@ Describe "SecureString conversion tests" -Tags "CI" { } It "Using invalid secure string with ConvertFrom-SecureString produces an exception message without value" { - { ConvertFrom-SecureString "1234" } | - Should -Throw ` - -ErrorId "CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand" ` - -ExpectedMessage 'Cannot bind parameter ''SecureString''. Cannot convert the value of type "System.String" to type "System.Security.SecureString".' + $ex = { ConvertFrom-SecureString "1234" } | Should -Throw -ErrorId "CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.ConvertFromSecureStringCommand" -PassThru + $ex.Exception.Message | Should -Not -Match "1234" } It "Using invalid securestring with cast produces an exception message without value" { - { [securestring]"1234" } | - Should -Throw ` - -ErrorId "ConvertToFinalInvalidCastException" ` - -ExpectedMessage 'Cannot convert the value of type "System.String" to type "System.Security.SecureString".' + $ex = { [securestring]"1234" } | Should -Throw -ErrorId "ConvertToFinalInvalidCastException" -PassThru + $ex.Exception.Message | Should -Not -Match "1234" } } diff --git a/test/powershell/engine/Basic/Credential.Tests.ps1 b/test/powershell/engine/Basic/Credential.Tests.ps1 index 9d7e4c8da24..850d40c9c52 100644 --- a/test/powershell/engine/Basic/Credential.Tests.ps1 +++ b/test/powershell/engine/Basic/Credential.Tests.ps1 @@ -7,9 +7,7 @@ Describe "Credential tests" -Tags "CI" { } It "Explicit credential cast with string produces an exception message without value" { - { [pscredential]"1234" } | - Should -Throw ` - -ErrorId "ConvertToFinalInvalidCastException" ` - -ExpectedMessage 'Cannot convert the value of type "System.String" to type "System.Management.Automation.PSCredential".' + $ex = { [pscredential]"1234" } | Should -Throw -ErrorId "ConvertToFinalInvalidCastException" -PassThru + $ex.Exception.Message | Should -Not -Match "1234" } }