Out-of-bounds write in the kitty text sizing protocol allows termination of the terminal process
Description
Out-of-bounds Write (CWE-787) in screen_handle_multicell_command() (kitty/screen.c), in the natural width branch of the text sizing protocol, in kitty from 0.40.0 before 0.49.0, which allows a program writing to the terminal to write past the end of a fixed-size buffer, because the function appends each codepoint of a grapheme cluster with lc.chars[lc.count++] = ch without any capacity check, while lc is declared by the RAII_ListOfChars macro (kitty/text-cache.h) as a four-element char_type array in the function's stack frame, so an OSC 66 escape code whose payload carries a grapheme cluster longer than four codepoints writes beyond that buffer, one 32-bit value per additional codepoint, in the order the codepoints appear. This results in termination of the kitty process and therefore of all its windows, tabs and child processes.
The condition guarding the append changed during the affected range without changing the defect. From 0.40.0 to 0.41.1 the append is taken when the codepoint is a combining character and the cluster is not empty. From 0.42.0 onwards it is taken when grapheme_segmentation_step() reports that the codepoint continues the current cell, or when the codepoint has width zero and the cluster is not empty. In both forms, any sequence of combining or zero-width codepoints following a base character reaches an append that performs no bounds check. The values written are Unicode scalar values decoded from the payload. Two filters narrow that range before the append: decode_utf8_safe_string() drops C0 and C1 codepoints, and the loop skips codepoints char_props_for() marks invalid. The writes are strictly sequential from the end of the buffer upward.
Where the same payload contains an earlier sequence that causes an intermediate flush through handle_variable_width_multicell_command(), that function calls ensure_space_for_chars(), which migrates the buffer from the stack to a heap allocation. Appends after such a flush overflow the heap allocation instead of the stack frame.
kitty is a single-process terminal, so the effect of the process terminating is not confined to the window that received the escape code.
Vulnerability type (CWE)
- CWE-787: Out-of-bounds Write
Affected versions
kitty from 0.40.0 before 0.49.0. screen_handle_multicell_command() was introduced in commit 540e030f and first released in v0.40.0; v0.39.1 and earlier do not contain the function. The unchecked append is present from that first release onwards, in the combining character branch up to v0.41.1 and in the refactored condition from v0.42.0. Every release from v0.40.0 to v0.48.2 inclusive is affected. Default status: unaffected.
Score (CVSS 4.0)
Medium (6.8)
CVSS:4.0/AV:L/AC:L/AT:N/PR:N/UI:P/VC:N/VI:N/VA:H/SC:N/SI:N/SA:N
The score reflects the impact established at the time of publication. This advisory makes no assertion, in either direction, about whether the out-of-bounds write can be developed into control-flow hijack or code execution.
A proof of concept reporting code execution built on this out-of-bounds write has been submitted to Secur0 and is under review. This advisory and the corresponding CVE record will be updated if that review changes the assessment.
Solution
Upgrade to kitty 0.49.0 or later.
Patch
Commit 7d2fbaad, which inserts ensure_space_for_chars(&lc, lc.count + 1) before the append, growing the buffer as required. The call covers both the stack and the heap case, since both pass through the same append statement.
Credits
- C4sh3R - finder
- Cristian Fernández Cornejo - analyst
- Xoán M. Otero Jorge - analyst
- Secur0 CNA - coordinator
- Kovid Goyal - remediation developer Discovery source: External
Official record: CVE-2026-80431
Related advisories
- CVE-2026-80430 - Medium severity
- CVE-2026-80432 - Medium severity