diff --git a/src/Runner.Worker/ActionCommandManager.cs b/src/Runner.Worker/ActionCommandManager.cs index 45b2fefdb..6375db293 100644 --- a/src/Runner.Worker/ActionCommandManager.cs +++ b/src/Runner.Worker/ActionCommandManager.cs @@ -381,6 +381,13 @@ namespace GitHub.Runner.Worker HostContext.SecretMasker.AddValue(command.Data); Trace.Info($"Add new secret mask with length of {command.Data.Length}"); + + // Also add each individual line. Typically individual lines are processed from STDOUT of child processes. + var split = command.Data.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); + foreach (var item in split) + { + HostContext.SecretMasker.AddValue(item); + } } } } diff --git a/src/Runner.Worker/Worker.cs b/src/Runner.Worker/Worker.cs index 1c83c4342..115789c4f 100644 --- a/src/Runner.Worker/Worker.cs +++ b/src/Runner.Worker/Worker.cs @@ -22,12 +22,13 @@ namespace GitHub.Runner.Worker { private readonly TimeSpan _workerStartTimeout = TimeSpan.FromSeconds(30); private ManualResetEvent _completedCommand = new ManualResetEvent(false); - + // Do not mask the values of these secrets - private static HashSet SecretVariableMaskWhitelist = new HashSet(StringComparer.OrdinalIgnoreCase){ + private static HashSet SecretVariableMaskWhitelist = new HashSet(StringComparer.OrdinalIgnoreCase) + { Constants.Variables.Actions.StepDebug, Constants.Variables.Actions.RunnerDebug - }; + }; public async Task RunAsync(string pipeIn, string pipeOut) { @@ -138,10 +139,10 @@ namespace GitHub.Runner.Worker HostContext.SecretMasker.AddValue(value); // Also add each individual line. Typically individual lines are processed from STDOUT of child processes. - var split = value.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries); + var split = value.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries); foreach (var item in split) { - HostContext.SecretMasker.AddValue(item.Trim()); + HostContext.SecretMasker.AddValue(item); } } } diff --git a/src/Test/L0/Worker/ActionCommandManagerL0.cs b/src/Test/L0/Worker/ActionCommandManagerL0.cs index ac5c4af93..cb53a6816 100644 --- a/src/Test/L0/Worker/ActionCommandManagerL0.cs +++ b/src/Test/L0/Worker/ActionCommandManagerL0.cs @@ -122,14 +122,14 @@ namespace GitHub.Runner.Common.Tests.Worker { _ec.Object.Global.EnvironmentVariables = new Dictionary(); var expressionValues = new DictionaryContextData - { - ["env"] = + { + ["env"] = #if OS_WINDOWS new DictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }} #else - new CaseSensitiveDictionaryContextData{ { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) }} + new CaseSensitiveDictionaryContextData { { Constants.Variables.Actions.AllowUnsupportedStopCommandTokens, new StringContextData(allowUnsupportedStopCommandTokens) } } #endif - }; + }; _ec.Setup(x => x.ExpressionValues).Returns(expressionValues); _ec.Setup(x => x.JobTelemetry).Returns(new List()); @@ -418,6 +418,31 @@ namespace GitHub.Runner.Common.Tests.Worker } } + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Worker")] + public void AddMaskWithMultilineValue() + { + using (TestHostContext hc = CreateTestContext()) + { + // Act + _commandManager.TryProcessCommand(_ec.Object, $"::add-mask::abc%0Ddef%0Aghi%0D%0Ajkl", null); + _commandManager.TryProcessCommand(_ec.Object, $"::add-mask:: %0D %0A %0D%0A %0D", null); + + // Assert + Assert.Equal("***", hc.SecretMasker.MaskSecrets("abc")); + Assert.Equal("***", hc.SecretMasker.MaskSecrets("def")); + Assert.Equal("***", hc.SecretMasker.MaskSecrets("ghi")); + Assert.Equal("***", hc.SecretMasker.MaskSecrets("jkl")); + Assert.Equal("***", hc.SecretMasker.MaskSecrets("abc\rdef\nghi\r\njkl")); + Assert.Equal("", hc.SecretMasker.MaskSecrets("")); + Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" ")); + Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" ")); + Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" ")); + Assert.Equal(" ", hc.SecretMasker.MaskSecrets(" ")); + } + } + private TestHostContext CreateTestContext([CallerMemberName] string testName = "") { var hostContext = new TestHostContext(this, testName); @@ -431,6 +456,7 @@ namespace GitHub.Runner.Common.Tests.Worker new InternalPluginSetRepoPathCommandExtension(), new SetEnvCommandExtension(), new WarningCommandExtension(), + new AddMaskCommandExtension(), }; foreach (var command in commands) {