From 502e854705f7830e08e2367e982f759db3ca601a Mon Sep 17 00:00:00 2001 From: Sebastien Tardif Date: Tue, 22 Sep 2026 19:07:09 -0700 Subject: [PATCH 1/2] fix(mxc): treat cmd /R as a command-mode switch Signed-off-by: Sebastien Tardif --- src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs | 4 +++- .../Mxc/MxcConfigBuilderTests.cs | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs b/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs index a80b3f345..ff7233206 100644 --- a/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs +++ b/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs @@ -552,8 +552,10 @@ private static bool SelectsCmdCommandMode(IReadOnlyList argv) if (argument.StartsWith("/c", StringComparison.OrdinalIgnoreCase) || argument.StartsWith("/k", StringComparison.OrdinalIgnoreCase) + || argument.StartsWith("/r", StringComparison.OrdinalIgnoreCase) || argument.Contains("/c", StringComparison.OrdinalIgnoreCase) - || argument.Contains("/k", StringComparison.OrdinalIgnoreCase)) + || argument.Contains("/k", StringComparison.OrdinalIgnoreCase) + || argument.Contains("/r", StringComparison.OrdinalIgnoreCase)) { return true; } diff --git a/tests/OpenClaw.Shared.Tests/Mxc/MxcConfigBuilderTests.cs b/tests/OpenClaw.Shared.Tests/Mxc/MxcConfigBuilderTests.cs index f6bf73302..747e379e6 100644 --- a/tests/OpenClaw.Shared.Tests/Mxc/MxcConfigBuilderTests.cs +++ b/tests/OpenClaw.Shared.Tests/Mxc/MxcConfigBuilderTests.cs @@ -790,6 +790,24 @@ public void Build_DirectArgv_LateCmdCommandMode_FailsClosed() Assert.Contains("canonical argv", error.Message, StringComparison.Ordinal); } + [Theory] + [InlineData("/R", "echo hi")] + [InlineData("/r", "prog", "hello&calc")] + [InlineData("/Recho hi")] + [InlineData("/rcommand")] + [InlineData("/d/s/recho hi")] + public void Build_DirectArgv_CmdSlashRCommandMode_FailsClosed(params string[] tail) + { + string[] argv = [ExpectedSystemCmdExe(), .. tail]; + using var argsDoc = JsonDocument.Parse(JsonSerializer.Serialize(new { argv })); + var request = RequestFor(BalancedPolicy()) with { Args = argsDoc.RootElement.Clone() }; + + var error = Assert.Throws( + () => BuildConfig(request, pathEnvVar: "")); + + Assert.Contains("canonical argv", error.Message, StringComparison.Ordinal); + } + [Fact] public void Build_CmdBootstrapRefsWithDelayedExpansionSyntax_FailsClosed() { From a4a9c9398fa10c8b403b6e6b67f12da124aac589 Mon Sep 17 00:00:00 2001 From: Sebastien Tardif Date: Wed, 23 Sep 2026 12:52:50 -0700 Subject: [PATCH 2/2] fix(mxc): drop redundant cmd command-mode prefixes StartsWith for /c, /k, and /r was already covered by Contains. /R still fails closed, and canonical /d /s /c is unchanged. Signed-off-by: Sebastien Tardif --- src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs b/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs index ff7233206..5e79f1c22 100644 --- a/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs +++ b/src/OpenClaw.Shared/Mxc/MxcConfigBuilder.cs @@ -550,10 +550,7 @@ private static bool SelectsCmdCommandMode(IReadOnlyList argv) if (!argument.StartsWith("/", StringComparison.Ordinal)) continue; - if (argument.StartsWith("/c", StringComparison.OrdinalIgnoreCase) - || argument.StartsWith("/k", StringComparison.OrdinalIgnoreCase) - || argument.StartsWith("/r", StringComparison.OrdinalIgnoreCase) - || argument.Contains("/c", StringComparison.OrdinalIgnoreCase) + if (argument.Contains("/c", StringComparison.OrdinalIgnoreCase) || argument.Contains("/k", StringComparison.OrdinalIgnoreCase) || argument.Contains("/r", StringComparison.OrdinalIgnoreCase)) {