Conversation
- Run command and message through ExecApprovalCommandDisplaySanitizer before the card renders them - Keep the approval request id unchanged - Tray test covers bidi, zero-width, and line-separator payloads Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
|
Codex review: needs real behavior proof before merge. Reviewed September 24, 2026, 3:26 PM ET / 19:26 UTC (Revision 5). ClawSweeper reviewWhat this changesThe branch sanitizes command and message text on Windows chat approval cards, limits unreviewable requests to Deny, and checks the pending card before sending an approval response to the Gateway. Merge readiness⛔ Blocked before merge - 5 items remain Current main still offers Allow on in-chat approvals without checking whether the command display is reviewable. This PR addresses that gap, and the latest commit resolves the reported missing-command explanation. The approval boundary still needs current-head, real-path proof before merge. Priority: P1 Review scores
Verification
How this fits togetherThe Windows tray receives execution approval events from the Gateway and turns them into chat cards. A user's card action returns through the chat provider to the Gateway approval RPC, which can permit command execution. flowchart LR
GatewayEvent[Gateway approval event] --> Sanitizer[Command display sanitizer]
Sanitizer --> CardDecision[Reviewable display?]
CardDecision --> ChatCard[Chat approval card]
ChatCard --> PendingCheck[Pending action check]
PendingCheck --> GatewayRPC[Gateway approval response]
Before merge
Findings
Agent review detailsSecurityNeeds attention: The patch narrows Allow eligibility, but current evidence does not establish rejection of a superseded approval before the final Gateway send. Review metrics
Merge-risk optionsMaintainer options:
Technical reviewBest possible solution: Keep Allow available only for fully reviewable, current approvals, with a visible Deny-only explanation and final-effect evidence for allowed, forbidden, and superseded responses before landing. Do we have a high-confidence way to reproduce the issue? Yes, from source: current main puts unsanitized Gateway command text on the card while offering Allow, and the new mapper tests exercise concealed and incomplete display cases. A live current-main card was not run in this review. Is this the best way to solve the issue? Yes, the sanitizer-status decision and provider guard are focused on the established approval flow. Real-path evidence is still needed to establish that the guard holds at the Gateway effect. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against 273b0182745a. LabelsLabel changes: No label changes. Label justifications:
EvidenceSecurity concerns:
What I checked:
Likely related people:
Rank-up movesOptional improvements that raise the rating; they are not merge blockers.
Rating scale
Overall follows the weaker of proof and patch quality. Workflow
HistoryReview history (4 earlier review cycles)
|
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9a0183f-460a-4854-b545-89033a081f21
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9a0183f-460a-4854-b545-89033a081f21
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: d9a0183f-460a-4854-b545-89033a081f21
|
Global triage: NEEDS_HUMAN_TEST. Take confidence 65%; recommendation confidence 92%; effort small-to-medium; risk medium. Reviewed exact head Owner: maintainer proof scheduler. Run strict |
Signed-off-by: Sebastien Tardif <SebTardif@ncf.ca>
|
c8a3785 keeps Deny as the only action when the command text is missing, and the card now says that no command was included so only Deny is available. Local filter Map_ApprovalRequestOffersOnlyDeny: 8 passed. Strict |
What Problem This Solves
Fixes the in-chat approval card showing a different command from the one Allow runs when gateway text contains hidden or reordered characters. A display that conceals or omits command content must never offer Allow.
User Impact
The card renders sanitized command and message text. When the command or message is oversized, truncated, or hides command syntax, only Deny is offered. A direct response call also cannot send Allow for that pending card. Reviewable commands retain Allow once, Always allow, and Deny.
Why This Change Was Made
The approval dialog already refuses commands that cannot be reviewed in full. The contributor patch sanitized the in-chat text but dropped the sanitizer's safety flags, so the card could still offer Allow on a suppressed or incomplete display. This follow-up uses
SanitizeWithStatuswhen mapping the card and checks the matching pending card's actions before callingexec.approval.resolve. The original contributor commit is preserved on this PR branch.Evidence
Final-head focused mapper/provider tests cover an oversized or truncated command, oversized or truncated message, secret redaction, zero-width Unicode concealment, and review-safe displays. A deny-only card rejects both direct Allow once and Always allow responses without sending a gateway RPC; Deny still sends the RPC.
Change Type
Scope
winnodeRequired proof pools
windows-winui-interactive: current-head in-chat approval-card display and Deny-only action need isolated visible proof.windows-wsl-mxc: exec approval safety boundary needs strict, non-skipping containment proof.windows-wsl-gateway-e2e: real gateway approval event and resolution path not yet exercised.Validation
./build.ps1: passed on Windows ARM64 atde0164bfef42479bc98ae8fc02a3df1a40b233db.dotnet test ./tests/OpenClaw.Shared.Tests/OpenClaw.Shared.Tests.csproj --no-restore: 4,104 passed, 35 skipped, 0 failed.dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --no-restore: 3,083 passed, 0 skipped, 0 failed.dotnet test ./tests/OpenClaw.Tray.Tests/OpenClaw.Tray.Tests.csproj --filter 'FullyQualifiedName~ChatEventMapperTests|FullyQualifiedName~RespondToPermissionAsync' --no-restore: 17 passed, 0 failed../scripts/validate-mxc-e2e.ps1without-AllowSkip: blocked, exits 1. Eleven peripheral tests passed, but six required MXC proofs skipped because this host reportsappcontainer-daclrather than MXC BaseContainer. This is not MXC merge proof; run on an MXC-capable Windows host.Real behavior proof
de0164bfef42479bc98ae8fc02a3df1a40b233dbon the original contributor branch, after integrating current main273b0182745a3093c0e09f306ca8a1fff6ef3c5a.Actions = [deny], while review-safe displays retain the original action set. The provider refuses direct Allow once/Always allow RPCs for a deny-only pending approval, retains the pending card, and lets Deny resolve it.run-app-local.ps1 -Isolated -AllowNonMain; starting the EXE directly would use real user state, so it was not attempted. A gateway-to-node MXC invocation was not exercised on this host. These proof pools remain open.Security Impact
Compatibility and Migration
Review Conversations