diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index abad70eda..3072ca4f0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -301,6 +301,7 @@ jobs: release_name: "v${{ steps.releaseNote.outputs.version }}" body: | ${{ steps.releaseNote.outputs.note }} + prerelease: true # Upload release assets (full runner packages) - name: Upload Release Asset (win-x64) diff --git a/releaseNote.md b/releaseNote.md index 4df3cc172..73dacbdad 100644 --- a/releaseNote.md +++ b/releaseNote.md @@ -7,6 +7,7 @@ ## Bugs - Use Global.Variables instead of JobContext and include action path/ref in the message. (#2214) +- Sanitize Windows ENVs (#2280) ## Misc - Allow '--disableupdate' in create-latest-svc.sh (#2201) diff --git a/src/Runner.Sdk/ProcessInvoker.cs b/src/Runner.Sdk/ProcessInvoker.cs index e303863b5..e46b2a057 100644 --- a/src/Runner.Sdk/ProcessInvoker.cs +++ b/src/Runner.Sdk/ProcessInvoker.cs @@ -264,7 +264,17 @@ namespace GitHub.Runner.Sdk { foreach (KeyValuePair kvp in environment) { +#if OS_WINDOWS + string tempKey = String.IsNullOrWhiteSpace(kvp.Key) ? kvp.Key : kvp.Key.Split('\0')[0]; + string tempValue = String.IsNullOrWhiteSpace(kvp.Value) ? kvp.Value : kvp.Value.Split('\0')[0]; + if(!String.IsNullOrWhiteSpace(tempKey)) + { + _proc.StartInfo.Environment[tempKey] = tempValue; + } +#else _proc.StartInfo.Environment[kvp.Key] = kvp.Value; + +#endif } } diff --git a/src/Test/L0/ProcessInvokerL0.cs b/src/Test/L0/ProcessInvokerL0.cs index d3d1b5486..6d99932e3 100644 --- a/src/Test/L0/ProcessInvokerL0.cs +++ b/src/Test/L0/ProcessInvokerL0.cs @@ -128,7 +128,76 @@ namespace GitHub.Runner.Common.Tests } } } +#if OS_WINDOWS + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Common")] + public async Task SetTestEnvWithNullInKey() + { + using (TestHostContext hc = new(this)) + { + Tracing trace = hc.GetTrace(); + Int32 exitCode = -1; + var processInvoker = new ProcessInvokerWrapper(); + processInvoker.Initialize(hc); + var stdout = new List(); + var stderr = new List(); + processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) => + { + trace.Info(e.Data); + stdout.Add(e.Data); + }; + processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) => + { + trace.Info(e.Data); + stderr.Add(e.Data); + }; + + exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"echo %TEST%\"", new Dictionary() { { "TEST\0second", "first" } }, CancellationToken.None); + + + trace.Info("Exit Code: {0}", exitCode); + Assert.Equal(0, exitCode); + Assert.Equal("first", stdout.First(x => !string.IsNullOrWhiteSpace(x))); + + } + } + + [Fact] + [Trait("Level", "L0")] + [Trait("Category", "Common")] + public async Task SetTestEnvWithNullInValue() + { + using (TestHostContext hc = new(this)) + { + Tracing trace = hc.GetTrace(); + + Int32 exitCode = -1; + var processInvoker = new ProcessInvokerWrapper(); + processInvoker.Initialize(hc); + var stdout = new List(); + var stderr = new List(); + processInvoker.OutputDataReceived += (object sender, ProcessDataReceivedEventArgs e) => + { + trace.Info(e.Data); + stdout.Add(e.Data); + }; + processInvoker.ErrorDataReceived += (object sender, ProcessDataReceivedEventArgs e) => + { + trace.Info(e.Data); + stderr.Add(e.Data); + }; + + exitCode = await processInvoker.ExecuteAsync("", "cmd.exe", "/c \"echo %TEST%\"", new Dictionary() { { "TEST", "first\0second" } }, CancellationToken.None); + + trace.Info("Exit Code: {0}", exitCode); + Assert.Equal(0, exitCode); + Assert.Equal("first", stdout.First(x => !string.IsNullOrWhiteSpace(x))); + + } + } +#endif [Fact] [Trait("Level", "L0")] [Trait("Category", "Common")] diff --git a/src/runnerversion b/src/runnerversion index b438eccda..1d7a5f586 100644 --- a/src/runnerversion +++ b/src/runnerversion @@ -1 +1 @@ -2.299.1 +2.299.2