fix(mxc): treat cmd /R as a command-mode switch - #1477
Conversation
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
Codex review: needs maintainer review before merge. Reviewed September 27, 2026, 1:21 PM ET / 17:21 UTC (Revision 10). ClawSweeper reviewWhat this changesThe branch makes the Windows MXC sandbox reject Regression provenancePossible regression — suspected (reviewed change). No predecessor PR is attributed. Merge readiness✅ Ready for maintainer review Current main does not reject Priority: P2 Review scores
Verification
How this fits togetherA Gateway flowchart LR
A[Gateway system.run request] --> B[Windows node approval]
B --> C[MXC command builder]
C --> D{Canonical cmd wrapper?}
D -->|Yes| E[AppContainer execution]
D -->|No command mode| E
D -->|Unsupported command mode| F[Sandbox denial]
Before mergeNone. Agent review detailsSecurityNone. Review metrics
Technical reviewBest possible solution: Keep one canonical cmd carrier contract across approvals and MXC, with Do we have a high-confidence way to reproduce the issue? Yes. Main's command-mode detector omits Is this the best way to solve the issue? Yes. Extending the existing detector and using the existing canonical carrier rejection path is a narrow fix consistent with the accepted compatibility decision. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 5a59535216ee. LabelsLabel changes:
Label justifications:
EvidenceWhat I checked:
Likely related people:
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (9 earlier review cycles; latest 8 shown)
|
|
Global triage: NEEDS_HUMAN_TEST. Take confidence 55%; recommendation confidence 92%; effort small; risk medium. Reviewed exact head |
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 <SebTardif@ncf.ca>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 9ba54a2d-477b-4b8e-994c-5fb3755d8b01
|
Maintainer decision: accept the fail-closed compatibility restriction. I now have a strict BaseContainer host. I am updating this original branch onto current |
|
Validated updated exact branch head Maintainer compatibility decision: accept fail-closed Validation
The validation process used task-local @clawsweeper re-review |
|
🦞👀 Re-review progress:
|
|
The failed Core/CLI job is unrelated to this PR's two-file MXC change. It timed out once in |
|
Maintainer merge override was attempted after three failed runs showed only unrelated Connection-suite flakes, but the repository ruleset correctly refused while |
What Problem
cmd /R is the same as /C, but SelectsCmdCommandMode only recognized /C and /K. cmd.exe /r prog hello&calc was serialized as raw argv, so cmd parsed the extra command.
Why
The approval card showed separate argv elements. The joined command then ran. This stays inside the sandbox when MXC is available. It is an approval mismatch, not a host escape.
User Impact
/R, /r, and an attached /Rcommand now fail closed unless the argv is the canonical cmd.exe /d /s /c carrier.
Evidence
Head
a4a9c9398fa10c8b403b6e6b67f12da124aac589.MxcAvailability.ProbewithOPENCLAW_WXC_EXECset to this head'stools\mxc\x64\wxc-exec.exereported AppContainer available and system.run allowed.MxcConfigBuilder.Buildforcmd.exe /R echo hithrewNotSupportedExceptionbeforeDirectAppContainerExecutor.ExecuteAsync:Direct cmd.exe command wrappers must use canonical argv: cmd.exe /d /s /c <command>.No sandbox process was started.The same executor then ran
cmd.exe /d /s /c whoami.exe. With Windows UI left off, the contained process exited-1073741502(0xC0000142) in about 137ms, tagmxc, empty stdout. WithSystemRunAllowWindowsUitrue, the same argv exited 0 in 145ms, tagmxc, and printed one account name. That name is redacted here.Required proof pools
/Ris rejected beforewxc-exec. A canonical/d /s /ccommand completed inside MXC when Windows UI was allowed.Validation
a4a9c9398fa10c8b403b6e6b67f12da124aac589.dotnet build src/OpenClaw.Tray.WinUI/OpenClaw.Tray.WinUI.csproj -p:Platform=x64 -p:RuntimeIdentifier=win-x64succeeded and copiedwxc-exec.exe.Build_DirectArgv_CmdSlashRCommandMode_FailsClosed: 5 passed, 0 failed../build.ps1exited 0.a4a9c9398fa10c8b403b6e6b67f12da124aac589: 3064 passed, 0 failed, 0 skipped, 3064 total. Tracked C# and XAML files were CRLF on disk for that run. The git commit was not changed./Rchange..\scripts\validate-mxc-e2e.ps1on this head, without-AllowSkip: exit 1. The port-lease unit tests passed.MirroredWslSafeGatewayPort_IsListeningAndRecorded,RealGateway_SystemRun_ExecutesThroughWindowsNodeMxcSandbox, andRealGateway_SystemRun_BlocksWritesToTrayDataDirectoryInMxcSandboxfailed. Setup stopped atGATEWAY_RESTART_PREPARATION_REFUSEDwhile restarting the fresh E2E gateway after the wizard, so those three proofs did not run the MXC path.Real behavior proof
/Rmust fail closed, and canonicalcmd.exe /d /s /cmust be able to run in the AppContainer.a4a9c9398fa10c8b403b6e6b67f12da124aac589,wxc-exec.exefrom that tray build.MxcConfigBuilder.Buildfor/R, thenDirectAppContainerExecutor.ExecuteAsyncforcmd.exe /d /s /c whoami.exe./Rthrew before execution. The canonical command with Windows UI allowed exited 0, tagmxc, stdout was one redacted account name. On 2026-09-25 the same tray build, heada4a9c939, was paired as a Windows node to a local OpenClaw 2026.9.6 gateway atws://127.0.0.1:18789.openclaw gateway call node.invokeforsystem.runreturned ok. The node log shows decision=Allow, containment=mxc, exitCode=0, timedOut=false, stdout length 23 for a powershell marker. Duration was about 625ms. The local exec policy was full with ask off, written on the node, because a remote full grant is refused./Rdid not start a sandbox process. The canonical carrier did run inside MXC. A later Gatewaynode.invokeofsystem.runalso ran inside MXC and exited 0.system.run. The fresh E2E gateway restart was refused. The UI-denied canonical launch exited0xC0000142and is not a successful run. An owner has not accepted the/Rcompatibility restriction.