fix(agents): strip C1 control characters (0x80-0x9f) in sanitizeForConsole#103226
fix(agents): strip C1 control characters (0x80-0x9f) in sanitizeForConsole#103226lsr911 wants to merge 3 commits into
Conversation
…nsole sanitizeForConsole filters C0 control characters (0x00-0x1f) and DEL (0x7f) but did not filter C1 controls (0x80-0x9f). The C1 range includes the CSI (Control Sequence Introducer) at 0x9b, which is an alternative prefix for ANSI escape sequences (equivalent to ESC [). An attacker who controls text routed through sanitizeForConsole could inject C1-based ANSI escapes into console/log output. Extend the filter to include the full C1 range (0x80-0x9f). Co-Authored-By: Claude <[email protected]>
…nalBufferText (#103274) renderTerminalBufferText filters C0 control characters (0x00-0x1f) and DEL (0x7f) but did not filter C1 controls (0x80-0x9f). The C1 range includes the CSI (Control Sequence Introducer) at 0x9b, an alternative ANSI escape prefix that stripAnsiSequences() may miss. Add the C1 range to CONTROL_BYTES_REGEX to strip all C1 bytes. Same pattern as the C1 fix in sanitizeForConsole (#103226). Co-authored-by: Claude <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
…nalBufferText (openclaw#103274) renderTerminalBufferText filters C0 control characters (0x00-0x1f) and DEL (0x7f) but did not filter C1 controls (0x80-0x9f). The C1 range includes the CSI (Control Sequence Introducer) at 0x9b, an alternative ANSI escape prefix that stripAnsiSequences() may miss. Add the C1 range to CONTROL_BYTES_REGEX to strip all C1 bytes. Same pattern as the C1 fix in sanitizeForConsole (openclaw#103226). Co-authored-by: Claude <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
|
Codex review: needs real behavior proof before merge. Reviewed July 10, 2026, 8:10 AM ET / 12:10 UTC. Summary PR surface: Source +3, Tests +64. Total +67 across 4 files. Reproducibility: yes. at source level with high confidence: current Review metrics: none identified. Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Next step before merge
Security Review findings
Review detailsBest possible solution: Keep the local helper because its compact-console semantics differ from Do we have a high-confidence way to reproduce the issue? Yes at source level with high confidence: current Is this the best way to solve the issue? No, not as submitted. The local predicate is the right implementation boundary, but the maintained regression must use a valid U+009B CSI form and the two proof-only files should not be merged. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against a13d2c4c9369. Label changesLabel justifications:
Evidence reviewedPR surface: Source +3, Tests +64. Total +67 across 4 files. View PR surface stats
Acceptance criteria:
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
Review history (1 earlier review cycle)
|
ClawSweeper review: the console-sanitization proof script belongs to openclaw#103226, not this gateway voice-wake fix. Remove it to keep the branch clean. Ref: openclaw#103210 review
|
@clawsweeper re-review |
|
🦞🧹 I asked ClawSweeper to review this item again. Re-review progress:
|
ClawSweeper review: the console-sanitization proof script belongs to openclaw#103226, not this gateway voice-wake fix. Remove it to keep the branch clean. Ref: openclaw#103210 review
…#103210) * fix(gateway): use truncateUtf16Safe for voice-wake trigger truncation Replace naive .slice(0, 64) with truncateUtf16Safe() in normalizeVoiceWakeTriggers to prevent surrogate pair splitting in user-configured voice wake trigger phrases. Voice wake triggers are user-configurable text strings that may contain emoji or non-BMP characters. A naive .slice(0, 64) at a surrogate pair boundary produces a lone surrogate, which corrupts the trigger text. Co-Authored-By: Claude <[email protected]> * test: add proof scripts for C1 sanitize and voice-wake UTF-16 * chore: remove unrelated proof script from voice-wake PR ClawSweeper review: the console-sanitization proof script belongs to #103226, not this gateway voice-wake fix. Remove it to keep the branch clean. Ref: #103210 review * fix(gateway): harden voice wake unicode boundary --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
|
Closing this branch. It mixes the console change with an unrelated voice-wake proof file, keeps a standalone proof script that should not ship, and the maintained CSI regression is malformed because U+009B is already the complete introducer. More importantly, terminal-control sanitization needs a deliberate sink-wide review rather than another isolated micro-patch. A clean replacement would need the valid U+009B sequence in maintained tests, no proof-only files, real escaped-byte/code-point evidence, and an audit showing why sibling output sinks are unaffected. |
…openclaw#103210) * fix(gateway): use truncateUtf16Safe for voice-wake trigger truncation Replace naive .slice(0, 64) with truncateUtf16Safe() in normalizeVoiceWakeTriggers to prevent surrogate pair splitting in user-configured voice wake trigger phrases. Voice wake triggers are user-configurable text strings that may contain emoji or non-BMP characters. A naive .slice(0, 64) at a surrogate pair boundary produces a lone surrogate, which corrupts the trigger text. Co-Authored-By: Claude <[email protected]> * test: add proof scripts for C1 sanitize and voice-wake UTF-16 * chore: remove unrelated proof script from voice-wake PR ClawSweeper review: the console-sanitization proof script belongs to openclaw#103226, not this gateway voice-wake fix. Remove it to keep the branch clean. Ref: openclaw#103210 review * fix(gateway): harden voice wake unicode boundary --------- Co-authored-by: Claude <[email protected]> Co-authored-by: Peter Steinberger <[email protected]>
|
@vincentkoc thanks — that's fair on all three points. Agreed the proof-only scripts and the stray voice-wake file shouldn't have shipped, and the CSI regression should use On the bigger point, I'd rather do the deliberate sink-wide pass than keep sending isolated patches. Before I invest the effort, does this shape sound right to you?
If you'd prefer a single shared helper over per-sink predicates, or a different boundary/owner, I'll follow that. I'll hold and close the 7 open siblings (#103379 #103380 #103381 #103382 #103383 #103402 #103405) and fold them into the one PR once you confirm the direction — happy to skip it entirely if you'd rather handle terminal-control sanitization internally. |
|
@vincentkoc thanks for the steer — I've rebuilt this as the deliberate sink-wide pass you asked for: #104362. How it maps to your feedback here:
It also folds in the seven isolated C1 PRs (now closed in its favour). Happy to reshape it — extract a shared predicate, or land in smaller reviewed batches — if you'd prefer. |
…g sinks Terminal-control sanitizers guard untrusted text before it reaches a terminal or log (CWE-117). The canonical range is C0 (0x00-0x1f), DEL (0x7f), and C1 (0x80-0x9f) - the range already used by the shared sanitizeForLog and by renderTerminalBufferText (openclaw#103274). C1 includes the 8-bit CSI introducer U+009B. Deliberate sink-wide pass: closes the C1 gap in twelve terminal/log output sinks, each keeping its own strip/escape/replace/truncate/reject action and gaining a focused valid-U+009B regression test. The PR body audits every other control-char sink (already-covered, deferred, or out-of-scope). Consolidates the isolated PRs openclaw#103379 openclaw#103380 openclaw#103381 openclaw#103382 openclaw#103383 openclaw#103402 Signed-off-by: lsr911 <[email protected]> openclaw#103405 and re-lands the sanitizeForConsole fix from openclaw#103226 cleanly.
What Problem This Solves
sanitizeForConsole()filters C0 control characters (0x00-0x1f) and DEL (0x7f) but leaves the C1 control range (0x80-0x9f) unhandled. The C1 range includes 0x9b (CSI), an alternative ANSI escape prefix.Why This Change Was Made
Add
(code >= 0x80 && code <= 0x9f)to the control character filter, covering all 32 C1 bytes. Same pattern as the merged #103274.Evidence
Standalone proof
Files Changed (1 file, +2/-1)
🤖 Generated with Claude Code