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 (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 (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 (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 (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.
gnome-terminal (VTE) - whole board rendered; title hijacked to terminal attack-class demo (safe); bidi reordered to report exe.doc.
konsole (KDE) - board rendered; bidi reordered to report exe.doc; title stored, not surfaced (keeps its own session name).
xfce4-terminal (VTE) - board rendered; title hijacked; bidi reordered to report exe.doc.
mate-terminal (VTE) - board rendered; title hijacked; bidi reordered to report exe.doc.
qterminal (LXQt) - board rendered; title hijacked in the bar and the tab; bidi unreordered.
xterm - whole board rendered; title hijacked; bidi shown unreordered (no bidi).
urxvt - whole board rendered; title hijacked; bidi unreordered.
st - whole board rendered; title hijacked; bidi unreordered.
alacritty (GPU) - board rendered; title hijacked; bidi unreordered. GPU rendering does not change the outcome.
kitty (GPU) - board rendered; honours the title hijack but its shell integration resets the title at the next prompt; bidi unreordered.
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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
konsole - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
xfce4-terminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
mate-terminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
qterminal - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
xterm - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
urxvt - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
st - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
alacritty - honours the charset shift - the ASCII bytes render as DEC line-drawing glyphs.
kitty - honours the charset shift - the ASCII bytes render as DEC 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still 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.
konsole - red-on-red: the warning lines are painted the same colour as their background, so they vanish into 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.
mate-terminal - red-on-red: the warning lines are painted the same colour as their background, so they vanish into 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.
xterm - red-on-red: the warning lines are painted the same colour as their background, so they vanish into 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.
st - red-on-red: the warning lines are painted the same colour as their background, so they vanish into 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.
kitty - red-on-red: the warning lines are painted the same colour as their background, so they vanish into 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - the window title is hijacked to the crafted label.
konsole - parses the OSC title but the default tab format does not surface it.
xfce4-terminal - the window title is hijacked to the crafted label.
mate-terminal - the window title is hijacked to the crafted label.
qterminal - the window title is hijacked to the crafted label.
xterm - the window title is hijacked to the crafted label.
urxvt - the window title is hijacked to the crafted label.
st - the window title is hijacked to the crafted label.
alacritty - the window title is hijacked to the crafted label.
kitty - honours the title hijack; shell integration resets it 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
kitty - a log line pops a real desktop notification (top-right), outside the terminal.
|
| 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.
| Terminal | OSC 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, st | Refused - OSC 52 write is off by default (xterm gates it behind the allowWindowOps resource). |
| qterminal (LXQt) | Refused. |
| secure-terminal | Refused - 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 |
|
| Keystroke / input injection (a reply typed as input) |
Never injected |
Replies become input |
|
| 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - the word reads as a clean administrator - the zero-width byte is invisible.
konsole - the word reads as a clean administrator - the zero-width byte is invisible.
xfce4-terminal - the word reads as a clean administrator - the zero-width byte is invisible.
mate-terminal - the word reads as a clean administrator - the zero-width byte is invisible.
qterminal - the word reads as a clean administrator - the zero-width byte is invisible.
xterm - the word reads as a clean administrator - the zero-width byte is invisible.
urxvt - the word reads as a clean administrator - the zero-width byte is invisible.
st - the word reads as a clean administrator - the zero-width byte is invisible.
alacritty - the word reads as a clean administrator - the zero-width byte is invisible.
kitty - the word reads as a clean administrator - the zero-width byte is invisible.
|
| 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
konsole - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
xfce4-terminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
mate-terminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
qterminal - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
xterm - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
urxvt - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
st - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
alacritty - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
kitty - renders a clean-looking example.com - the Cyrillic look-alike is indistinguishable.
|
| 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
konsole - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
xfce4-terminal - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
mate-terminal - reorders the RLO bytes - the line reads left-to-right as POC-CORPUS-CANARY-FIRED, hiding the real byte order.
qterminal - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
xterm - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
urxvt - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
st - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
alacritty - leaves the bytes in logical (scrambled) order; the invisible RLO is present but unmarked.
kitty - leaves the bytes in logical (scrambled) order; the invisible RLO 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - garbled, replacement glyphs.
konsole - garbled, selection artifacts.
xfce4-terminal - garbled.
mate-terminal - garbled.
qterminal - garbled.
xterm - garbled, stuck reverse-video.
urxvt - garbled.
st - garbled.
alacritty - garbled.
kitty - garbled, replacement glyphs.
|
| Pasted-command smuggling (pastejacking, bracketed-paste bypass) |
Sanitized + warned |
Rides along hidden |
|
| 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 (CLI, Detail) - each non-ASCII byte named inline as <U+XXXX NAME>, the safe default view. secure-terminal (CLI, Show) - printable unicode rendered as its glyph, risk-tinted; invisible, bidi and control bytes still boxed. secure-terminal (TUI, Box) - opt-in full-screen layout; every non-ASCII cell still an inert risk-coloured box, the title untouched. secure-terminal (TUI, Show) - full-screen layout with printable unicode shown as risk-tinted glyphs; invisible and bidi bytes still boxed.
gnome-terminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
konsole - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
xfce4-terminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
mate-terminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
qterminal - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
xterm - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
urxvt - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
st - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
alacritty - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
kitty - stuck full-screen on the unrestored alternate screen; the prompt is gone until reset.
|
| Memory safety of the parser |
 |
        
|
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 |
|
| Two forms: GUI app and CLI wrapper |
GUI + CLI wrapper |
- |
|