Skip to content

Fix terminal escape sequence injection in rendered API text#1

Open
MoizIbnYousaf wants to merge 1 commit intobddicken:mainfrom
MoizIbnYousaf:fix/sanitize-terminal-escapes
Open

Fix terminal escape sequence injection in rendered API text#1
MoizIbnYousaf wants to merge 1 commit intobddicken:mainfrom
MoizIbnYousaf:fix/sanitize-terminal-escapes

Conversation

@MoizIbnYousaf
Copy link
Copy Markdown

Problem

Tweet text, author names, user bios, and API error messages are passed directly to OpenTUI Text() without sanitization. Since OpenTUI does not strip escape sequences internally, a crafted post containing terminal escape sequences reaches the terminal emulator and gets interpreted as commands.

Concrete attack vectors:

  • OSC 52 (\x1b]52;c;BASE64\x07) silently overwrites the user's clipboard
  • CSI 2J (\x1b[2J) clears the terminal screen
  • OSC 0 (\x1b]0;FAKE\x07) changes the terminal title (phishing)
  • 8-bit C1 CSI (\x9b) bypasses 7-bit-only filters
  • Kitty graphics sequences can overlay fake UI elements

Any X user can trigger this by posting a tweet with embedded escape bytes.

Fix

  • Add sanitizeText() in src/sanitize.ts that strips 7-bit ESC sequences, 8-bit C1 control codes (0x80-0x9F), and remaining control characters while preserving tabs and newlines
  • Apply it in post-card.ts (tweet text, author name, username), user-info.ts (name, username, bio), header-bar.ts (view title), and status-bar.ts (error messages)
  • Add image URL allowlist in post-image-preview.ts so Jimp.read() only fetches from known X CDN hosts (pbs.twimg.com, abs.twimg.com, video.twimg.com, ton.twimg.com), preventing SSRF via manipulated API responses

What it does not change

  • No new dependencies
  • No changes to API calls, auth flow, or app behavior
  • Emoji, unicode, URLs, and normal text pass through unchanged

Untrusted text from the X API (tweet bodies, author names, user bios,
error messages) was passed directly to OpenTUI Text() components.
A crafted post containing terminal escape sequences could hijack the
clipboard (OSC 52), clear the screen (CSI 2J), or spoof the terminal
title.

Add sanitizeText() that strips 7-bit ESC sequences, 8-bit C1 control
codes, and remaining control characters before rendering. Also add an
image URL allowlist so Jimp only fetches from known X CDN hosts.
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