diff --git a/PSReadLine/History.cs b/PSReadLine/History.cs index 4f7e466b2..9c90ce503 100644 --- a/PSReadLine/History.cs +++ b/PSReadLine/History.cs @@ -565,10 +565,24 @@ public static AddToHistoryOption GetDefaultAddToHistoryOption(string line) return AddToHistoryOption.MemoryAndFile; } + // The input contains at least one match of some sensitive patterns, so now we need to further + // analyze the input using the ASTs to see if it should actually be considered sensitive. bool isSensitive = false; + ParseError[] parseErrors = _singleton._parseErrors; + + // We need to compare the text here, instead of simply checking whether or not '_ast' is null. + // This is because we may need to update from history file in the middle of editing an input, + // and in that case, the '_ast' may be not-null, but it was not parsed from 'line'. Ast ast = string.Equals(_singleton._ast?.Extent.Text, line) ? _singleton._ast - : Parser.ParseInput(line, out _, out _); + : Parser.ParseInput(line, out _, out parseErrors); + + if (parseErrors != null && parseErrors.Length > 0) + { + // If the input has any parsing errors, we cannot reliably analyze the AST. We just consider + // it sensitive in this case, given that it contains matches of our sensitive pattern. + return AddToHistoryOption.MemoryOnly; + } do { diff --git a/PSReadLine/ReadLine.cs b/PSReadLine/ReadLine.cs index 7fd302394..2d97a7f37 100644 --- a/PSReadLine/ReadLine.cs +++ b/PSReadLine/ReadLine.cs @@ -721,6 +721,7 @@ private void Initialize(Runspace runspace, EngineIntrinsics engineIntrinsics) _mark = 0; _emphasisStart = -1; _emphasisLength = 0; + _ast = null; _tokens = null; _parseErrors = null; _inputAccepted = false; diff --git a/test/HistoryTest.cs b/test/HistoryTest.cs index a7a6e5c49..6d724e005 100644 --- a/test/HistoryTest.cs +++ b/test/HistoryTest.cs @@ -201,7 +201,8 @@ public void SensitiveHistoryDefaultBehavior_Two() "Get-SecretInfo -Name mytoken; Get-SecretVault; Register-SecretVault; Remove-Secret apikey; Set-Secret", // 'Set-Secret' Not saved to file. "Set-SecretInfo -Name apikey; Set-SecretVaultDefault; Test-SecretVault; Unlock-SecretVault -password $pwd; Unregister-SecretVault -SecretVault vaultInfo", "Get-ResultFromTwo -Secret1 (Get-Secret -Name blah -AsPlainText) -Secret2 $secret2", - "Get-ResultFromTwo -Secret1 (Get-Secret -Name blah -AsPlainText) -Secret2 sdv87ysdfayf798hfasd8f7ha" // '-Secret2' has expr-value argument. Not saved to file. + "Get-ResultFromTwo -Secret1 (Get-Secret -Name blah -AsPlainText) -Secret2 sdv87ysdfayf798hfasd8f7ha", // '-Secret2' has expr-value argument. Not saved to file. + "$environment -brand $brand -userBitWardenEmail $bwuser -userBitWardenPassword $bwpass" // '-userBitWardenPassword' matches sensitive pattern and it has parsing error. Not save to file. }; string[] expectedSavedItems = new[] {