Skip to content

fix: prevent terminal query response leakage#17

Merged
linletian merged 2 commits intodevelopfrom
fix/top-cli-exited-abnormal-char
Mar 13, 2026
Merged

fix: prevent terminal query response leakage#17
linletian merged 2 commits intodevelopfrom
fix/top-cli-exited-abnormal-char

Conversation

@linletian
Copy link
Owner

Summary

  • Add terminal connection state machine (ttyState) to prevent query leakage
  • Add isTerminalQueryResponse() filter to block xterm.js auto-generated responses
  • Fix ttyState reset on instance stop and prevent reconnection for stopped instances
  • Document known limitations and future considerations in ARCHITECTURE.md §5.9

Problem

When switching terminal windows or after TUI programs (like opencode CLI) exit, xterm.js sends terminal query responses that appear as garbage text in the shell:

  • ;1R (cursor position report fragment)
  • rgb:0b0b/1010/2020 (OSC color response fragment)
  • ?2027;0$y (DEC private mode report fragment)

Root Cause

Shell sends query → xterm.js receives → generates response → forwards via onData() → sent back to PTY → displayed as garbage

Changes

  1. State Machine: IDLE → CONNECTING → HANDSHAKING → READY → DISCONNECTING
  2. Focus Prevention: Terminal only gains focus when ttyState === 'READY'
  3. Response Filter: isTerminalQueryResponse() blocks known response patterns
  4. State Reset: ttyState properly reset when instance stops
  5. Reconnection Logic: Only reconnect if instance is still running

Documentation

  • Added docs/TERMINAL_FILTER_REVIEW.md with detailed analysis
  • Added docs/ARCHITECTURE.md §5.9 with data flow diagram
  • Added code comments linking to review document

Known Limitations

⚠️ See docs/TERMINAL_FILTER_REVIEW.md for complete analysis:

  • Cannot distinguish user-intentional ESC sequences from auto responses
  • Regex may have edge cases or cause false positives
  • Small coordinate reports may be incorrectly filtered
  • Some response types (DSR, etc.) not explicitly covered
  • Filter is in input path; alternative approaches documented

Test Plan

  • Verified Connection Lost issue resolved (missing variable declaration fixed)
  • Verified terminal focus timing (state machine)
  • Verified garbage text reduction after TUI program exit
  • Build passes: go build ./...

linletian and others added 2 commits March 12, 2026 23:18
- Add DISCONNECTING state to match documented state machine (§5.1)
- Add ttyStateCheckInterval to track polling timer
- Clear polling timer in disconnectTTY() to prevent leaks
- Add max retries (10) with timeout protection for state transitions
- Force transition to IDLE after max retries as recovery mechanism
- Remove redundant local variable isReady, use ttyState uniformly
- Document terminal protocol timing in ARCHITECTURE.md §5

This ensures robust state management during instance switching
and prevents race conditions when connectTTY() is called rapidly.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
…iltering

Problem: When switching terminal windows or after TUI programs exit,
xterm.js sends terminal query responses that appear as garbage text
in the shell (e.g., ;1R, rgb:0b0b/1010/2020, ?2027;0$y).

Root cause: xterm.js generates responses to terminal queries and
forwards them via term.onData() callback, which then get sent back
to PTY and displayed.

Changes:
- Add ttyState state machine (IDLE→CONNECTING→HANDSHAKING→READY)
- Prevent terminal focus until WebSocket is READY
- Add isTerminalQueryResponse() filter in term.onData()
- Fix ttyState reset on instance stop
- Prevent WebSocket reconnection for stopped instances

Documentation:
- Add §5.9 Terminal Query Response Filtering to ARCHITECTURE.md
- Add detailed code comments linking to TERMINAL_FILTER_REVIEW.md
- TERMINAL_FILTER_REVIEW.md documents known limitations and risks

Known limitations (see docs/TERMINAL_FILTER_REVIEW.md):
- Cannot distinguish user-intentional ESC sequences from auto responses
- Regex may have edge cases or false positives
- Some response types not explicitly covered
@linletian linletian merged commit 2d8db44 into develop Mar 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant