Hostile bytes, side by side

The same hostile board, ten terminals.

A normal terminal interprets untrusted bytes - random data, program output, a hostile log - as escape sequences: they can garble the screen, force colours, rewrite the window title, or overwrite the clipboard. secure-terminal reduces the identical bytes to inert printable ASCII.

The same hostile board, fed to ten popular emulators and to secure-terminal on shipped defaults, each on an isolated headless display. Tested 2026-08-12.

Choose the secure-terminal view and the terminal to compare against. Expand any row for the full detail.
Attack / behaviour secure-terminal vs gnome-terminal konsole xfce4-terminal mate-terminal qterminal xterm urxvt st alacritty kitty
Merely viewing a file (cat, a log, a diff) Safe Triggers tricks

Every escape trick on this page fires just by being displayed - viewing an attacker's log or diff is enough, no execution needed. The board below is one safe, display-only file shown in a normal terminal and in secure-terminal, side by side: the normal terminal interprets the escapes; secure-terminal reduces the identical bytes to inert, marked ASCII. Switch the compared terminal and the secure-terminal view with the controls above.

secure-terminal (CLI, Box) - the whole board reduced to inert ASCII: title untouched, alt-screen stripped, line-drawing literal, the hidden SECRET forced readable, every hidden/look-alike byte an inert risk-coloured box.
secure-terminal in CLI Box mode on the combined board: title still reads secure-terminal, the plaintext warning and scrollback intact, the DEC frame shown as literal characters, the SGR-hidden SECRET forced readable, each homoglyph, zero-width, bidi and foreign byte an inert box coloured by its risk class.
secure-terminal (CLI, Detail) - each byte named inline as <U+XXXX NAME>: the Cyrillic a reads <U+0430 CYRILLIC SMALL LETTER A>, the RTL override <U+202E RIGHT-TO-LEFT OVERRIDE>.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode renders as its glyph, risk-tinted by class, so useful foreign text stays readable while look-alikes are flagged by colour; invisible, bidi, zero-width and heavy Zalgo (stacked combining) bytes still become inert boxes.
secure-terminal in CLI Show mode: printable unicode such as Greek text and homoglyphs render as their glyphs but tinted by risk class, while invisible, bidi, zero-width and heavy Zalgo (stacked combining) bytes are shown as inert boxes; the title still reads secure-terminal.
secure-terminal (TUI, Box) - full-screen layout allowed on the alternate screen, yet every non-ASCII cell is still an inert risk-coloured box and the title stays untouched. Reveal and Detail need CLI mode (the fixed grid cannot expand a codepoint inline), so TUI offers Box and Show.
secure-terminal with TUI mode on: the full-screen layout and box-drawing charset are allowed, but every homoglyph, zero-width, bidi and foreign byte is still an inert boxed placeholder coloured by its risk class, and the window title still reads secure-terminal.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as readable glyphs (risk-tinted); invisible, bidi, zero-width and heavy Zalgo (stacked combining) bytes still boxed, the box-drawing frame drawn as real lines, and the title untouched.
secure-terminal with TUI and Show both on: the full-screen board draws with real box-drawing borders, printable unicode renders as risk-tinted glyphs, and invisible, bidi, zero-width and heavy Zalgo bytes stay inert boxes; the title still reads secure-terminal.
gnome-terminal (VTE) - whole board rendered; title hijacked to terminal attack-class demo (safe); bidi reordered to report exe.doc.
gnome-terminal displaying the combined board: the window title is hijacked, every attack-class row renders, and the bidi row is visually reordered to report exe.doc because VTE implements bidi.
konsole (KDE) - board rendered; bidi reordered to report exe.doc; title stored, not surfaced (keeps its own session name).
konsole displaying the combined board: every class renders, the bidi row is reordered to report exe.doc, and the title bar keeps konsole's own session name rather than surfacing the hijacked title.
xfce4-terminal (VTE) - board rendered; title hijacked; bidi reordered to report exe.doc.
xfce4-terminal displaying the combined board: title hijacked, every class rendered, and the bidi row visually reordered to report exe.doc because VTE implements bidi.
mate-terminal (VTE) - board rendered; title hijacked; bidi reordered to report exe.doc.
mate-terminal displaying the combined board: title hijacked, every class rendered, bidi row reordered to report exe.doc.
qterminal (LXQt) - board rendered; title hijacked in the bar and the tab; bidi unreordered.
qterminal displaying the combined board: the hijacked title shows in both the window title bar and the tab, every class renders, and the bidi row is unreordered.
xterm - whole board rendered; title hijacked; bidi shown unreordered (no bidi).
xterm displaying the combined board: the window title is hijacked, every class row renders, and the bidi row reads in logical order because xterm does not reorder bidi.
urxvt - whole board rendered; title hijacked; bidi unreordered.
urxvt displaying the combined board: title hijacked, every class rendered, bidi row unreordered.
st - whole board rendered; title hijacked; bidi unreordered.
st displaying the combined board: title hijacked, every class rendered, bidi row unreordered.
alacritty (GPU) - board rendered; title hijacked; bidi unreordered. GPU rendering does not change the outcome.
alacritty, a modern GPU terminal, displaying the combined board: title hijacked, every class rendered, bidi row unreordered.
kitty (GPU) - board rendered; honours the title hijack but its shell integration resets the title at the next prompt; bidi unreordered.
kitty, a modern GPU terminal, displaying the combined board: every class rendered and bidi unreordered; kitty honours the OSC title hijack but its shell integration resets the title at the returned prompt.

One safe, display-only board (the corpus tui-showcase PoC) carrying every display-class at once - a hijacked title, a DEC frame, a homoglyph example.com, a bidi report cod.exe, zero-width and invisible bytes, an SGR-hidden SECRET, an OSC 8 link and the alternate-screen switch. Click any shot for full size. Reproduce it.

Each neutralised non-ASCII byte is an inert box coloured by its risk class, never by the program:  bidi controls,  homoglyphs,  zero-width/invisible,  control bytes,  other non-ASCII (honest foreign text).

Escape sequences in output (repaint, cursor, hide text) Not parsed Interpreted

A normal terminal treats program output as commands: move the cursor, erase and repaint lines, hide or fake text. secure-terminal parses none of it apart from safe colour and four line-local edits (CSI C/D/G/K) clamped to the line being written, so any stray control byte shows as an inert box and nothing a program prints can repaint the screen or reach a line already scrolled past. See the compatibility page for exactly which sequences are neutralised.

secure-terminal - the DEC charset shift is inert: the shifted bytes are shown as their literal ASCII, not line-drawing glyphs, and the prompt returns clean.
secure-terminal displaying the escape payload: the DEC charset shift is inert, the bytes shown as literal ASCII, and the prompt returned clean.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
konsole - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
xfce4-terminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
mate-terminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
qterminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
xterm - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
urxvt - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
st - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
alacritty - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
kitty - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
honours the DEC charset shift, so the ASCII bytes render as line-drawing glyphs.
Stuck colour that hides text (red-on-red) Contrast-guarded Text hidden

secure-terminal's colour is not colourless. Safe ANSI colour is on by default (turn it off with the Colors toggle or NO_COLOR). The difference is the contrast guard: it forces any colour to stay readable against the background, so a crafted log's stuck red-on-red - designed to hide text - is shown as legible text instead. Colour that can never conceal, and a palette a program cannot repaint.

secure-terminal - the stuck red-on-red colour is kept, but the contrast guard forces the text legible: the NOTICE box and the lines a normal terminal hides are readable.
secure-terminal displaying the contrast payload: the stuck red-on-red is kept but the contrast guard forces the text to a legible colour, so the otherwise-hidden warning is readable.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
gnome-terminal displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
konsole - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
konsole displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
xfce4-terminal - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
xfce4-terminal displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
mate-terminal - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
mate-terminal displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
qterminal - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
qterminal displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
xterm - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
xterm displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
urxvt - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
urxvt displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
st - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
st displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
alacritty - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
alacritty displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
kitty - red-on-red: the warning lines are painted the same colour as their background, so they vanish into a solid red block.
kitty displaying the crafted log: the stuck red foreground on a red background hides the warning text inside a solid red block.
Window / tab title hijack (OSC 0/2) Never touched gnome-terminal, xfce4-terminal, mate-terminal, qterminal, xterm, urxvt, st, alacritty: Hijacked konsole: Stored, not shown kitty: Reset at prompt

An OSC 0/2 escape in output renames your window or tab to anything - a fake "production" label, a spoofed context. On seven of the ten emulators the attacker-controlled title reads back in the title bar. Two are partial: konsole parses and stores it but the default tab format omits the program-set title (not shown by default); kitty honours it, but its default shell integration resets the title to the cwd at the next prompt, so the hijack shows until then. secure-terminal never sets the title from output; a banner notes the blocked escape.

secure-terminal - the title bar still reads secure-terminal; the OSC title escape is neutralised and a banner flags the blocked escape.
secure-terminal displaying the title payload: the window title still reads secure-terminal, the OSC title-set neutralised and flagged by a banner.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
konsole - parses the OSC title but the default tab format does not surface it.
displaying the crafted log: konsole stores the OSC title but its default tab format keeps its own session name.
xfce4-terminal - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
mate-terminal - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
qterminal - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
xterm - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
urxvt - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
st - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
alacritty - the window title is hijacked to the crafted label.
displaying the crafted log: the window title bar is hijacked to the attacker-set label.
kitty - honours the title hijack; shell integration resets it at the next prompt.
displaying the crafted log: kitty honours the OSC title hijack but its shell integration resets the title at the next prompt.
Desktop notification spoof (OSC 9) Neutralised kitty: Pops a popup the others: No OSC 9

kitty (like iTerm2) implements OSC 9, so program output can raise a real desktop notification with attacker-chosen text, outside the terminal window entirely. The others in this set do not implement it, so the class does not apply to them. secure-terminal's CLI mode strips the escape - no popup, inert text, a banner flags it. The payload is the corpus notification-spoof-kitty-2022 class.

secure-terminal - OSC-9 notification neutralised: no popup, inert text, a banner flags the blocked escape.
secure-terminal displaying the same build log: no desktop notification appears, the text is inert, and a banner notes the blocked OSC desktop-notification escape.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
kitty - a log line pops a real desktop notification (top-right), outside the terminal.
kitty: cat-ing a build log pops a desktop notification in the top-right corner. No action needed.
Clipboard write from output (OSC 52) Off by default konsole, alacritty, kitty: Honored gnome-terminal, xfce4-terminal, mate-terminal, qterminal, xterm, urxvt, st: Refused

The OSC 52 clipboard write is the one class a screenshot cannot show - its effect is on your system clipboard, not the screen. So we measured it directly: for each terminal we seeded the X clipboard with a sentinel, cat'd the corpus osc52-clipboard-write payload, and read the real clipboard back (via PyQt6). If the token landed, output overwrote your clipboard. Tested 2026-08-12 on shipped defaults, window focused.

TerminalOSC 52 clipboard write (shipped default)
konsole (KDE), alacritty (GPU), kitty (GPU)Honored - viewing the payload silently overwrote the clipboard.
gnome-terminal, xfce4-terminal, mate-terminal (VTE)Refused - mainline VTE ships no OSC 52 write at all.
xterm, urxvt, stRefused - OSC 52 write is off by default (xterm gates it behind the allowWindowOps resource).
qterminal (LXQt)Refused.
secure-terminalRefused - OSC 52 write is off by default; opt-in per tab.

Three of the ten let untrusted output silently overwrite your clipboard on their defaults. This is a real per-terminal verdict: clipboard-verdict.sh reads the real clipboard back after each terminal views the payload. Note the twist: konsole does not surface a hijacked title, yet does honour the clipboard write.

Clipboard read / query reflection (OSC 52 read, DA, answerback) Never answered Reflects queries

A terminal and the program it runs share one two-way channel (the pseudo-terminal). When output contains a query escape - say ESC[c ("what terminal are you?") - a normal terminal answers by writing the reply back onto that same channel, and the input side of that channel is the program's keyboard. So a query hidden in attacker output makes the terminal inject bytes as if you had typed them - no keypress needed. That reflection is how a remote program reads your clipboard back through an OSC 52 read query, and how a title or answerback report becomes spoofed input.

David Leadbeater's 2023 review catalogued the class across current terminals. The CVEs it collects are on other emulators - CVE-2022-45872 (iTerm2), CVE-2022-47583 / CVE-2023-39726 (mintty), CVE-2022-23465 (SwiftTerm) - so they prove the class, not these ten. For the compared set we measured it directly: the fingerprintability table fires each query at every terminal and records the reply - a typical emulator answers device-attributes, cursor-position, answerback and colour queries; secure-terminal stays silent. secure-terminal answers no query by default - an automated test asserts zero bytes are ever written back. The one exception is clipboard read, opt-in and human-gated once per tab.

Keystroke / input injection (a reply typed as input) Never injected Replies become input

A terminal and the program it runs share one two-way channel: a reply the terminal writes back to a query escape arrives on the same wire as your keystrokes, so a query hidden in attacker output can make bytes appear as if you typed them - no keypress needed. That is how a reflected report, answerback or clipboard-read reply turns into injected input. What actually lands depends on which queries each terminal answers (our fingerprint measurement records the reply per class of terminal) and whether it reaches the shell mid-line. Modern defaults mitigate turning a reflected reply into a run command - bracketed paste, empty or one-shot answerback, no auto-execute of replies (the same default mitigation the cat-execution row notes) - but the bytes still arrive as input. secure-terminal answers no query by default and an automated test asserts zero bytes are ever written back, so nothing from output can arrive as input.

Reproduce it (safe): the query-report class is stored read-safe as hex in the corpus - see answerback-injection and device-status-reflection-rxvt-2021. Decode with the corpus reproduce.py; each PoC carries a canary token, never a live command.

Remote code execution from output (cat-execution) Not parsed Mitigated by default

Historically, escape sequences could be chained toward command execution - an answerback string set from output and then auto-replayed, or a report reflected into the shell as a runnable line. This is the class behind the old "a log file can run code" warnings. Modern terminals mitigate it by default (empty/one-shot answerback, no auto-execute of replies, bracketed paste), so plain cat of a hostile file is not a live remote-code-execution path on a current, default-configured emulator - we do not claim it is (the full CVE trail - iTerm2, xterm, Windows Terminal, and the 2024 Ghostty / iTerm2 recurrence with a public proof of concept - and a safe demo are on output lies: merely viewing a file can run commands). It is shown here because the mechanism (output reflected onto the input wire) is the same one the reflection and input-injection rows measure. secure-terminal parses no escape sequences at all, so the class cannot arise: there is nothing to reflect and nothing to auto-run.

Reproduce it (safe): view the display-only-safe board (below) - it changes only the display and runs nothing - and the reflected-report PoCs in the corpus, all canary-token, never a live command.

Invisible / zero-width characters Marked / boxed Drawn as nothing

Zero-width and other invisible characters draw nothing, so a command or a paste can carry hidden bytes you never see - the heart of the pastejacking demo. secure-terminal names each inline as <U+XXXX NAME> by default, or shows an inert risk-coloured box.

secure-terminal - the hidden zero-width byte is an inert box between admin and istrator; you can see it is there.
secure-terminal displaying the zero-width payload: the hidden U+200B is drawn as an inert box between admin and istrator.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
konsole - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
xfce4-terminal - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
mate-terminal - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
qterminal - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
xterm - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
urxvt - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
st - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
alacritty - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
kitty - the word reads as a clean administrator - the zero-width byte is invisible.
displaying the zero-width payload: the word reads as a clean administrator with no sign of the hidden zero-width byte.
Homoglyph look-alikes Boxed / named Renders identical

Non-ASCII characters identical in shape to ASCII (a Cyrillic a, a Greek o) make a fake command or URL read as legitimate - a clean example.com that is not. Universal across terminals. secure-terminal flags the look-alike byte as a coloured box, or names its exact codepoint in Detail mode.

secure-terminal - the Cyrillic look-alike is an inert coloured box; Detail mode names it <U+0430 CYRILLIC SMALL LETTER A>.
secure-terminal displaying the homoglyph domain: the Cyrillic look-alike byte is drawn as an inert coloured box.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
konsole - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
xfce4-terminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
mate-terminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
qterminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
xterm - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
urxvt - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
st - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
alacritty - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
kitty - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
displaying the homoglyph domain: it renders as a clean-looking example.com, the Cyrillic look-alike indistinguishable from ASCII.
Bidi reorder / Trojan Source Neutralised gnome-terminal, konsole, xfce4-terminal, mate-terminal: Reorders text qterminal, xterm, urxvt, st, alacritty, kitty: Present, not reordered

Bidirectional control characters reorder how a line renders, so report cod.exe displays as report exe.doc. The four bidi-aware terminals here (the three VTE apps and konsole) actually reorder it; the rest leave the bytes present but in logical order - weaker, but the invisible controls are still there and unmarked. secure-terminal neutralises the bidi controls entirely. Proof: corpus trojan-source-bidi-2021.

secure-terminal - the bidi controls are neutralised: the line reads in logical order, the RLO shown as an inert box.
secure-terminal displaying the bidi payload: the RLO control is an inert box and the text reads in logical order.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
displaying the bidi payload: the RLO override reorders the bytes so the line reads left-to-right as the forward canary token.
konsole - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
displaying the bidi payload: the RLO override reorders the bytes so the line reads left-to-right as the forward canary token.
xfce4-terminal - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
displaying the bidi payload: the RLO override reorders the bytes so the line reads left-to-right as the forward canary token.
mate-terminal - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
displaying the bidi payload: the RLO override reorders the bytes so the line reads left-to-right as the forward canary token.
qterminal - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
displaying the bidi payload: the bytes stay in logical scrambled order and the invisible RLO override is present but unmarked.
xterm - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
displaying the bidi payload: the bytes stay in logical scrambled order and the invisible RLO override is present but unmarked.
urxvt - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
displaying the bidi payload: the bytes stay in logical scrambled order and the invisible RLO override is present but unmarked.
st - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
displaying the bidi payload: the bytes stay in logical scrambled order and the invisible RLO override is present but unmarked.
alacritty - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
displaying the bidi payload: the bytes stay in logical scrambled order and the invisible RLO override is present but unmarked.
kitty - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
displaying the bidi payload: the bytes stay in logical scrambled order and the invisible RLO override is present but unmarked.
Raw random bytes (screen garble, stuck colour) Inert ASCII Garbled

head -c 1200 /dev/random at a prompt: every normal terminal is garbled, most with stuck reverse-video or replacement glyphs, and the visible mess clears only with reset. secure-terminal shows every non-ASCII byte as inert, risk-coloured ASCII with the prompt returning clean.

secure-terminal - printable ASCII as-is, every other byte an inert risk-coloured box; title unchanged, prompt returns clean.
secure-terminal displaying random bytes: printable ASCII as-is and every other byte an inert box coloured by risk class, title unchanged, the returned prompt on its own line.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - garbled, replacement glyphs.
gnome-terminal displaying random bytes: garbled with replacement glyphs.
konsole - garbled, selection artifacts.
konsole displaying random bytes: garbled.
xfce4-terminal - garbled.
xfce4-terminal displaying random bytes: garbled.
mate-terminal - garbled.
mate-terminal displaying random bytes: garbled.
qterminal - garbled.
qterminal displaying random bytes: garbled.
xterm - garbled, stuck reverse-video.
xterm displaying random bytes: garbled with stuck reverse-video.
urxvt - garbled.
urxvt displaying random bytes: garbled.
st - garbled.
st displaying random bytes: garbled.
alacritty - garbled.
alacritty displaying random bytes: garbled.
kitty - garbled, replacement glyphs.
kitty displaying random bytes: garbled with replacement glyphs.
Pasted-command smuggling (pastejacking, bracketed-paste bypass) Sanitized + warned Rides along hidden

A command copied from a web page can carry a whole second command chained on with && and an invisible byte at the seam - it draws nothing, so a normal terminal shows no sign it is there. Modern shells mitigate multi-line paste with bracketed paste, but it is opt-in and one-line && tricks slip through. secure-terminal catches any invisible, control or bidi character in a paste, names what is hidden, and lets you drop it to ASCII or cancel. See the live pastejacking demo and the full still-applicable list on the attacks page.

secure-terminal's paste review - the same hostile curl | bash paste, held inside the window before a byte reaches the shell: each hidden character named inline, and a preview of exactly what each send button would deliver (stripped to ASCII, or with printable unicode kept). Rendered headless from the real review bar.
secure-terminal's in-window paste-review bar showing a hostile curl-bash paste four ways: the original as it arrives, each hidden character named inline in its risk-class colour, and the two send previews - stripped to ASCII, or with the look-alike domain kept but the invisibles dropped.
Full-screen programs (ssh, vim, htop, tmux) Yes, cell-filtered Yes

Running full-screen programs is a capability, not a vulnerability - every terminal does it. secure-terminal's opt-in TUI mode grants the layout, but every cell is still character-filtered: look-alikes stay boxed and the title stays off. TUI mode grants layout, never an unfiltered cell. Only run programs you trust - in TUI mode a program can still draw a misleading interface within its own screen.

secure-terminal - the alt-screen switch is stripped; the board renders inline and the prompt returns clean (opt-in TUI mode grants the layout, still cell-filtered).
secure-terminal displaying the alt-screen payload: the alternate-screen switch is stripped, the content renders inline and the prompt returns clean.
secure-terminal (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view.
secure-terminal in CLI Detail mode: every non-ASCII byte expanded inline to its Unicode name.
secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed.
secure-terminal in CLI Show mode: printable unicode rendered as risk-tinted glyphs while invisible, bidi and control bytes stay inert boxes.
secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched.
secure-terminal in TUI Box mode: full-screen layout allowed, but every non-ASCII cell is still an inert risk-coloured box and the title is untouched.
secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
secure-terminal in TUI Show mode: full-screen layout with printable unicode shown as risk-tinted glyphs while invisible and bidi bytes stay boxed.
gnome-terminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
konsole - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
xfce4-terminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
mate-terminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
qterminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
xterm - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
urxvt - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
st - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
alacritty - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
kitty - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
displaying the alt-screen payload: stuck full-screen on the unrestored alternate screen with the prompt gone until reset.
Memory safety of the parser secure-terminal: Python parser, memory-safe gnome-terminal: C++ parser, memory-unsafekonsole: C++ parser, memory-unsafexfce4-terminal: C++ parser, memory-unsafemate-terminal: C++ parser, memory-unsafeqterminal: C++ parser, memory-unsafexterm: C parser, memory-unsafeurxvt: C++ parser, memory-unsafest: C parser, memory-unsafealacritty: Rust parser, memory-safekitty: C parser, memory-unsafe

The code that parses untrusted bytes is where a memory-safety bug bites, so this row is scoped to the escape-sequence parser. Nine of the ten emulators parse in C or C++ (xterm, urxvt, st, VTE for gnome/xfce4/mate-terminal, konsole, qterminal, kitty's in-tree vt-parser.c); only alacritty (Rust) and secure-terminal (Python) parse in a memory-safe language. Each badge links to the exact parser source.

Honest caveat: the claim is scoped to the parser. secure-terminal's runtime embeds CPython (C) and PyQt6/Qt (C++) like any Python GUI app; what is memory-safe is the parsing and sanitizing code itself, which is pure Python with no C extension in the parse path. Read this as "fewer places for a bug to hide", not a proof there are none - see what does not apply, and what still might.

Harmful command itself (curl | sh, a wrong rm) Opt-in handler (CLI) None

No terminal protects you from a harmful command itself. Deciding that curl x | sh (curl bash pipe) or a subtly wrong rm is dangerous is a judgment call, not a parsing rule, so no terminal can catch it by design. secure-terminal keeps that judgment out of the terminal but provides an opt-in hook: before a command runs in CLI mode it can call an external handler you configure, which may warn, suggest a safer command, or ask you to confirm. The terminal ships no AI and no policy of its own; the logic lives in the handler.

Two forms: GUI app and CLI wrapper GUI + CLI wrapper -

GUI and CLI. secure-terminal is a graphical application; secure-terminal-cli is the same safe core as a command-line wrapper - it runs a shell or command in a pseudo-terminal and sanitizes the output before it reaches your existing terminal, so a plain console or an SSH session gets safe display without the GUI. It sanitizes what a program displays; it does not gate keystrokes or judge commands.

Method & evidence

One payload set, run in ten terminal emulators and in secure-terminal, each on its own isolated headless display, each command typed at an interactive shell so every shot shows the prompt, the command, its output and the state of the prompt after it. The combined board subsumes the crafted-log, homoglyph, bidi and alt-screen cases in one frame; the raw random stream is the no-crafted-escapes control. Both payloads and the capture harness are published.

Did we rig it against your terminal? No - the shipped default behind each resultShowHide

Every emulator was launched with a fresh, empty config - a throwaway HOME and XDG_CONFIG_HOME - so each ran on its shipped defaults; the only options passed are window size and font. Here is the exact default behind each title-hijack result:

TerminalThe shipped default that produces itVerify
gnome-terminal, xfce4-terminal, mate-terminal (VTE)VTE applies the OSC 0/2 title; all three apps default to writing the program-set title, and VTE implements bidi so it reorders the Trojan-Source row.VTE source
xtermallowTitleOps defaults to true, so an OSC 0/1/2 escape sets the title.xterm(1)
urxvtOSC 0/1/2 title changes are honoured and ungated.urxvt(1)
stxsettitle() acts on OSC 0/1/2; not gated by allowwindowops.st x.c
konsoleParses and stores the OSC title, but the default tab format omits the shell-set title (%w) - stored, not surfaced (not shown by default).konsole source
qterminalThe VT layer honours the OSC title and shows it in the tab.qterminal source
alacrittywindow.dynamic_title defaults to true; GPU rendering is not a factor here.alacritty(5)
kittyHonours the OSC title; shell_integration is enabled by default and resets the title at the next prompt, so the hijack shows until then.kitty shell integration

The clipboard, notification, alt-screen and homoglyph results are all shipped defaults too, reproduced from the read-safe terminal-poc-corpus payloads.

Reproduce it yourselfShowHide

The board shown above is published as one read-safe text file - the same board behind the output-lies terminal demo. cat-ing it changes only the display: it sets the window title and switches to the alternate screen, both undone by reset. It does not touch your clipboard, type at your prompt, or run anything. View it in a throwaway terminal, then feed the same file to secure-terminal:

# the same board, hosted read-safe as text:

curl -O https://output-lies.github.io/demos/terminal-attack-demo-WARNING-display-only-safe.txt

# plain cat - only the display changes; `reset` restores it:

cat terminal-attack-demo-WARNING-display-only-safe.txt reset

# the same file through secure-terminal - each hidden, look-alike, bidi and invisible # byte is marked or boxed, the title left untouched, the alt-screen stripped:

secure-terminal-cli cat terminal-attack-demo-WARNING-display-only-safe.txt

That file carries the display classes (title, alt-screen, homoglyph, bidi, zero-width, SGR-hidden text, OSC 8). For the clipboard, notification and other non-display classes - and every PoC stored read-safe as hex - see the terminal-poc-corpus.

Regenerating the screenshots is a footnote: comparison-capture.sh drives each emulator headless and screenshots it. An automated, always-on version ships as the opt-in terminal-resilience-tests in dist-ai.

Get secure-terminal

Two forms - a graphical app and the secure-terminal-cli wrapper - share one safe core. The forms and the opt-in harmful-command hook are rows in the matrix above.