Skip to content

(#2377) fix(shell): sanitize terminal-facing output and harden path checks#2378

Open
vjanelle wants to merge 1 commit intosipeed:mainfrom
vjanelle:upstream/terminal-output-sanitization
Open

(#2377) fix(shell): sanitize terminal-facing output and harden path checks#2378
vjanelle wants to merge 1 commit intosipeed:mainfrom
vjanelle:upstream/terminal-output-sanitization

Conversation

@vjanelle
Copy link
Copy Markdown

@vjanelle vjanelle commented Apr 6, 2026

Harden terminal-facing output in the exec tool and logger by escaping control and format characters before they reach the console or LLM-facing output. Refine exec workspace path validation so normalized relative paths inside the working directory remain allowed while real escapes are blocked.

Type of change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • ✨ New feature (non-breaking change which adds functionality)
  • 📖 Documentation update
  • ⚡ Code refactoring (no functional changes, no api changes)

🤖 AI Code Generation

  • 🤖 Fully AI-generated (100% AI, 0% Human)
  • 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
  • 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

N/A

  • Reference URL: N/A

  • Reasoning: Raw ANSI escape sequences and Unicode bidi overrides should not be able to alter operator terminal state. The previous workspace guard also rejected any path containing ../ even when the normalized path still resolved inside the working directory.

  • Hardware: PC

  • OS: Linux

  • Model/Provider: GPT-5.2 / OpenAI codex

  • Channels: internal terminal / exec tool usage

Click to view Logs/Screenshots
  • Added tests for ANSI and bidi escaping in terminal-facing output
  • Added tests for allowing normalized in-workspace relative traversal
  • Added tests for blocking relative traversal that escapes the working directory
  • My code/docs follow the style of this project.
  • I have performed a self-review of my own changes.
  • I have updated the documentation accordingly.

…path checks

Harden terminal-facing output in the exec tool and logger by escaping control and format characters before they reach the console or LLM-facing output. Refine exec workspace path validation so normalized relative paths inside the working directory remain allowed while real escapes are blocked.

- [x] 🐞 Bug fix (non-breaking change which fixes an issue)
- [ ] ✨ New feature (non-breaking change which adds functionality)
- [ ] 📖 Documentation update
- [ ] ⚡ Code refactoring (no functional changes, no api changes)

- [ ] 🤖 Fully AI-generated (100% AI, 0% Human)
- [x] 🛠️ Mostly AI-generated (AI draft, Human verified/modified)
- [ ] 👨‍💻 Mostly Human-written (Human lead, AI assisted or none)

N/A

- **Reference URL:** N/A
- **Reasoning:** Raw ANSI escape sequences and Unicode bidi overrides should not be able to alter operator terminal state. The previous workspace guard also rejected any path containing `../` even when the normalized path still resolved inside the working directory.

- **Hardware:** PC
- **OS:** Linux
- **Model/Provider:** GPT-5.2 / OpenAI codex
- **Channels:** internal terminal / exec tool usage

<details>
<summary>Click to view Logs/Screenshots</summary>

- Added tests for ANSI and bidi escaping in terminal-facing output
- Added tests for allowing normalized in-workspace relative traversal
- Added tests for blocking relative traversal that escapes the working directory

</details>

- [x] My code/docs follow the style of this project.
- [x] I have performed a self-review of my own changes.
- [ ] I have updated the documentation accordingly.
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 6, 2026

CLA assistant check
All committers have signed the CLA.

@sipeed-bot sipeed-bot bot added type: bug Something isn't working domain: tool go Pull requests that update go code labels Apr 7, 2026
Copy link
Copy Markdown
Collaborator

@yinwm yinwm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on hardening the terminal output and path validation! The overall approach is solid. I have a few items that need attention before this can be merged:

Blocking:

  1. Merge conflict + Linter failure — Please rebase onto latest main and fix the lint errors.
  2. C1 control characters gapEscapeControlChars doesn't catch C1 control characters (U+0080–U+009F). In UTF-8 these are encoded as 0xC2 0x800xC2 0x9F. While most modern terminals use 7-bit CSI, some still interpret 8-bit C1 codes (e.g., 0x9B = CSI). Consider adding r >= 0x80 && r <= 0x9f to the escape condition.

Please verify:
3. Logger Component color in TTY modeFormatPrepare injects ANSI color codes into the Component field (\x1b[33m...\x1b[0m), but formatFieldValue now calls EscapeControlChars on all field values. If zerolog's ConsoleWriter calls FormatFieldValue for the Component part, the injected color codes will be escaped to literal text. Could you verify this doesn't break TTY color output?

Non-blocking suggestions:
4. Consider adding dedicated unit tests for EscapeControlChars in pkg/termutil/ covering C0, C1, DEL, bidi, zero-width chars, and edge cases.
5. Shell variable expansion (\/../path) can theoretically bypass the path traversal check since filepath.Abs treats \ as a literal directory name. This is low-risk given the AI agent context, but worth documenting as a known limitation.

@yinwm
Copy link
Copy Markdown
Collaborator

yinwm commented Apr 12, 2026

Additional finding from deeper review:

Timeout path bypasses EscapeControlChars — In runSync, when a command times out (context.DeadlineExceeded), the function returns early at line 443-448 with the raw output embedded in the message, skipping the EscapeControlChars call at line 470. This means a command that intentionally stalls past the timeout can inject raw ANSI escape sequences and bidi overrides into both ForLLM and ForUser.

The fix is straightforward: apply EscapeControlChars to output before the timeout check, or apply it to msg before the early return.

@vjanelle
Copy link
Copy Markdown
Author

@yinwm any opinions about ZWJ and complex emoji?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain: tool go Pull requests that update go code type: bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants