From b1b1237cb68f2df28bc53506503422ff82b95565 Mon Sep 17 00:00:00 2001 From: TheCakeIsNaOH Date: Sun, 6 Mar 2022 15:33:42 -0600 Subject: [PATCH 1/2] (#1310) List remembered arguments This adds the listing of remembered arguments to the list/info commands It only grabs the arguments when --local-only is specified, then decrypts and outputs them. Requires --verbose to be listed on the command line. --- .../scenarios/ListScenarios.cs | 4 ++++ .../infrastructure.app/services/NugetService.cs | 10 ++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/chocolatey.tests.integration/scenarios/ListScenarios.cs b/src/chocolatey.tests.integration/scenarios/ListScenarios.cs index cf72223c35..d00930ddd8 100644 --- a/src/chocolatey.tests.integration/scenarios/ListScenarios.cs +++ b/src/chocolatey.tests.integration/scenarios/ListScenarios.cs @@ -21,6 +21,7 @@ using NuGet.Configuration; using FluentAssertions; using FluentAssertions.Execution; +using NUnit.Framework; namespace chocolatey.tests.integration.scenarios { @@ -140,7 +141,10 @@ public void Should_contain_packages_and_versions_with_a_pipe_between_them() MockLogger.ContainsMessage("upgradepackage|1.0.0").Should().BeTrue(); } + // Windows only because decryption fallback on Mac/Linux logs a message [Fact] + [WindowsOnly] + [Platform(Exclude = "Mono")] public void Should_only_have_messages_related_to_package_information() { MockLogger.Messages.Should() diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs index eed43df34c..8316938a52 100644 --- a/src/chocolatey/infrastructure.app/services/NugetService.cs +++ b/src/chocolatey/infrastructure.app/services/NugetService.cs @@ -192,6 +192,7 @@ it is possible that incomplete package lists are returned from a command foreach (var pkg in NugetList.GetPackages(config, _nugetLogger, _fileSystem)) { var package = pkg; // for lamda access + string packageArgumentsUnencrypted = null; ChocolateyPackageMetadata packageLocalMetadata; string packageInstallLocation = null; @@ -218,6 +219,10 @@ it is possible that incomplete package lists are returned from a command } deploymentLocation = packageInfo.DeploymentLocation; + if (!string.IsNullOrWhiteSpace(packageInfo.Arguments)) + { + packageArgumentsUnencrypted = "\n Remembered Package Arguments: " + (packageInfo.Arguments.ContainsSafe(" --") && packageInfo.Arguments.ToStringSafe().Length > 4 ? packageInfo.Arguments : NugetEncryptionUtility.DecryptString(packageInfo.Arguments)); + } } if (!config.QuietOutput) @@ -244,7 +249,7 @@ Package url{6} Tags: {9} Software Site: {10} Software License: {11}{12}{13}{14}{15}{16} - Description: {17}{18}{19} + Description: {17}{18}{19}{20} ".FormatWith( package.Title.EscapeCurlyBraces(), package.Published.GetValueOrDefault().UtcDateTime.ToShortDateString(), @@ -279,7 +284,8 @@ Package url{6} package.Summary != null && !string.IsNullOrWhiteSpace(package.Summary.ToStringSafe()) ? "\r\n Summary: {0}".FormatWith(package.Summary.EscapeCurlyBraces().ToStringSafe()) : string.Empty, package.Description.EscapeCurlyBraces().Replace("\n ", "\n").Replace("\n", "\n "), !string.IsNullOrWhiteSpace(package.ReleaseNotes.ToStringSafe()) ? "{0} Release Notes: {1}".FormatWith(Environment.NewLine, package.ReleaseNotes.EscapeCurlyBraces().Replace("\n ", "\n").Replace("\n", "\n ")) : string.Empty, - !string.IsNullOrWhiteSpace(deploymentLocation) ? "{0} Deployed to: '{1}'".FormatWith(Environment.NewLine, deploymentLocation) : string.Empty + !string.IsNullOrWhiteSpace(deploymentLocation) ? "{0} Deployed to: '{1}'".FormatWith(Environment.NewLine, deploymentLocation) : string.Empty, + packageArgumentsUnencrypted != null ? packageArgumentsUnencrypted : string.Empty )); } } From 6595cf0fd4d1e1d0a222ddf880b8eddee9febaae Mon Sep 17 00:00:00 2001 From: Gary Ewan Park Date: Wed, 8 May 2024 04:08:55 -0700 Subject: [PATCH 2/2] (#1310) Ensure sensitive arguments are redacted This commit makes sure that no potentially sensitive arguments are displayed to the end user. This makes use of the same code that is currently being used in Chocolatey GUI, for providing the same function. Now that this code exists in Chocolatey CLI, at some point in the future, Chocolatey GUI can be updated to use it, rather than maintaining the code in two places. This new code makes use of the existing SensitiveArgumentsProvided method to establish whether the argument is deemed as sensitive, and if it is, "[REDACTED ARGUMENT]" is output, rather than the value itself. This new function has been created as a static method, so that it can be used easily in the Chocolatey GUI codebase. --- .../services/NugetService.cs | 4 +- .../utility/ArgumentsUtility.cs | 69 +++++++++++++++++++ 2 files changed, 72 insertions(+), 1 deletion(-) diff --git a/src/chocolatey/infrastructure.app/services/NugetService.cs b/src/chocolatey/infrastructure.app/services/NugetService.cs index 8316938a52..e91910412c 100644 --- a/src/chocolatey/infrastructure.app/services/NugetService.cs +++ b/src/chocolatey/infrastructure.app/services/NugetService.cs @@ -221,7 +221,9 @@ it is possible that incomplete package lists are returned from a command deploymentLocation = packageInfo.DeploymentLocation; if (!string.IsNullOrWhiteSpace(packageInfo.Arguments)) { - packageArgumentsUnencrypted = "\n Remembered Package Arguments: " + (packageInfo.Arguments.ContainsSafe(" --") && packageInfo.Arguments.ToStringSafe().Length > 4 ? packageInfo.Arguments : NugetEncryptionUtility.DecryptString(packageInfo.Arguments)); + var decryptedArguments = ArgumentsUtility.DecryptPackageArgumentsFile(_fileSystem, packageInfo.Package.Id, packageInfo.Package.Version.ToNormalizedStringChecked()); + + packageArgumentsUnencrypted = "\n Remembered Package Arguments: \n {0}".FormatWith(string.Join(Environment.NewLine + " ", decryptedArguments)); } } diff --git a/src/chocolatey/infrastructure.app/utility/ArgumentsUtility.cs b/src/chocolatey/infrastructure.app/utility/ArgumentsUtility.cs index 53df50dbbf..a1a5bd58a5 100644 --- a/src/chocolatey/infrastructure.app/utility/ArgumentsUtility.cs +++ b/src/chocolatey/infrastructure.app/utility/ArgumentsUtility.cs @@ -15,6 +15,9 @@ // limitations under the License. using System; +using System.Collections.Generic; +using chocolatey.infrastructure.app.nuget; +using chocolatey.infrastructure.filesystem; namespace chocolatey.infrastructure.app.utility { @@ -50,6 +53,72 @@ public static bool SensitiveArgumentsProvided(string commandArguments) ; } + public static IEnumerable DecryptPackageArgumentsFile(IFileSystem fileSystem, string id, string version) + { + var argumentsPath = fileSystem.CombinePaths(ApplicationParameters.InstallLocation, ".chocolatey", "{0}.{1}".FormatWith(id, version)); + var argumentsFile = fileSystem.CombinePaths(argumentsPath, ".arguments"); + + var arguments = string.Empty; + + // Get the arguments decrypted in here and return them + try + { + if (fileSystem.FileExists(argumentsFile)) + { + arguments = fileSystem.ReadFile(argumentsFile); + } + } + catch (Exception ex) + { + "chocolatey".Log().Error("There was an error attempting to read the contents of the .arguments file for version '{0}' of package '{1}'. See log file for more information.".FormatWith(version, id)); + } + + if (string.IsNullOrEmpty(arguments)) + { + "chocolatey".Log().Debug("Unable to locate .arguments file for version '{0}' of package '{1}'.".FormatWith(version, id)); + yield break; + } + + // The following code is borrowed from the Chocolatey codebase, should + // be extracted to a separate location in choco executable so we can re-use it. + var packageArgumentsUnencrypted = arguments.Contains(" --") && arguments.ToStringSafe().Length > 4 + ? arguments + : NugetEncryptionUtility.DecryptString(arguments); + + // Lets do a global check first to see if there are any sensitive arguments + // before we filter out the values used later. + var sensitiveArgs = SensitiveArgumentsProvided(packageArgumentsUnencrypted); + + var packageArgumentsSplit = + packageArgumentsUnencrypted.Split(new[] { " --" }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var packageArgument in packageArgumentsSplit.OrEmpty()) + { + var isSensitiveArgument = sensitiveArgs && SensitiveArgumentsProvided(string.Concat("--", packageArgument)); + + var packageArgumentSplit = + packageArgument.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries); + + var optionName = packageArgumentSplit[0].ToStringSafe(); + var optionValue = string.Empty; + + if (packageArgumentSplit.Length == 2 && isSensitiveArgument) + { + optionValue = "[REDACTED ARGUMENT]"; + } + else if (packageArgumentSplit.Length == 2) + { + optionValue = packageArgumentSplit[1].ToStringSafe().UnquoteSafe(); + if (optionValue.StartsWith("'")) + { + optionValue.UnquoteSafe(); + } + } + + yield return "--{0}{1}".FormatWith(optionName, string.IsNullOrWhiteSpace(optionValue) ? string.Empty : "=" + optionValue); + } + } + #pragma warning disable IDE0022, IDE1006 [Obsolete("This overload is deprecated and will be removed in v3.")] public static bool arguments_contain_sensitive_information(string commandArguments)