Skip to content

fix(terminal): strip C1 control characters (0x80-0x9f) in renderTerminalBufferText#103274

Merged
steipete merged 2 commits into
openclaw:mainfrom
lsr911:fix/terminal-buffer-c1-control-chars
Jul 10, 2026
Merged

fix(terminal): strip C1 control characters (0x80-0x9f) in renderTerminalBufferText#103274
steipete merged 2 commits into
openclaw:mainfrom
lsr911:fix/terminal-buffer-c1-control-chars

Conversation

@lsr911

@lsr911 lsr911 commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

What Problem This Solves

renderTerminalBufferText() in src/gateway/terminal/buffer-text.ts filters C0 control characters (0x00-0x1f) and DEL (0x7f) via CONTROL_BYTES_REGEX, but leaves the C1 control range (0x80-0x9f) unhandled.

The C1 range includes 0x9b (CSI — Control Sequence Introducer), an alternative ANSI escape prefix equivalent to ESC [. While stripAnsiSequences() is called first and handles standard ESC-based sequences, the C1 CSI (0x9b) variant may survive in terminal output.

Same pattern as sanitizeForConsole (#103226) and the comprehensive sanitizeForLog in packages/terminal-core/src/ansi.ts.

Why This Change Was Made

Add the C1 range (0x80-0x9f) to CONTROL_BYTES_REGEX alongside the existing C0 range. No behavioral change for ASCII-only terminal output.

User Impact

Terminal buffer text containing C1 control bytes no longer leaks ANSI escape sequences into agent tool output displayed via terminal.text. No impact on normal terminal output which is predominantly ASCII.

Evidence

C1 CSI stripping behavior

// In Node.js REPL:
> const csi = String.fromCharCode(0x9b);
> console.log(`text${csi}[31mred`)
// Before fix: renders as red text via C1 ANSI injection
// After fix:  "text[31mred" — CSI stripped

Same proven pattern as #103226

sanitizeForConsole C1 fix follows identical approach. The C1 range (0x80-0x9f) covers all 32 C1 control bytes.

Files Changed (1 file, +5/-2)

 src/gateway/terminal/buffer-text.ts | 7 +++++--

🤖 Generated with Claude Code

…nalBufferText

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]>
@steipete

Copy link
Copy Markdown
Contributor

Land-ready maintainer pass complete.

  • Extended the existing terminal-text residual filter through DEL/C1 while preserving tabs and the separate CR/LF overwrite path; complete ANSI sequences remain owned by terminal-core.
  • Renamed the ranges precisely and kept one focused regression for BEL, U+0080, U+009F, and the standalone C1 CSI byte after reviewing the renderer and terminal-core siblings.
  • Exact prepared head 1df6da914a8c70b651c2af9db6708f6d16509cd3 passed full hosted CI: https://github.com/openclaw/openclaw/actions/runs/29070142477
  • Fresh autoreview, review artifacts, and OPENCLAW_TESTBOX=1 scripts/pr prepare-run 103274 passed.

Merging with contributor credit preserved. Thanks @lsr911.

@steipete
steipete merged commit a3f9f35 into openclaw:main Jul 10, 2026
97 checks passed
@steipete

Copy link
Copy Markdown
Contributor

Merged via squash.

github-actions Bot pushed a commit to Desicool/openclaw that referenced this pull request Jul 10, 2026
…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]>
lsr911 added a commit to lsr911/openclaw that referenced this pull request Jul 12, 2026
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gateway Gateway runtime size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants