Disallow parsing color specs as conf files for clone-in-kitty and edit-in-kitty

This commit is contained in:
Kovid Goyal
2026-04-26 10:47:24 +05:30
parent 2ead0de844
commit 5623ce52bb
4 changed files with 15 additions and 10 deletions

View File

@@ -228,7 +228,7 @@ Detailed list of changes
- Password input in kittens: hide the cursor and display a blinking 🔒 at the end of typed characters to make it visually clear the user is entering a password - Password input in kittens: hide the cursor and display a blinking 🔒 at the end of typed characters to make it visually clear the user is entering a password
- edit-in-kitty: Ignore environment variables as some editors execute code present in env vars - edit-in-kitty: Ignore environment variables as some editors execute code present in env vars. Similarly ignore conf file specifications for colors.
- Command palette :sc:`command_palette`: nicer grouping of aliases and combined actions (:pull:`9819`) - Command palette :sc:`command_palette`: nicer grouping of aliases and combined actions (:pull:`9819`)

View File

@@ -266,7 +266,7 @@ over SSH when using :doc:`kittens/ssh`.
The :command:`clone-in-kitty` command takes almost all the same arguments as the The :command:`clone-in-kitty` command takes almost all the same arguments as the
:doc:`launch <launch>` command, so you can open a new tab instead or a new OS :doc:`launch <launch>` command, so you can open a new tab instead or a new OS
window, etc. Arguments of launch that can cause code execution or that don't window, etc. Arguments of launch that that don't
make sense when cloning are ignored. Most prominently, the following options are make sense when cloning are ignored. Most prominently, the following options are
ignored: :option:`--allow-remote-control <launch --allow-remote-control>`, ignored: :option:`--allow-remote-control <launch --allow-remote-control>`,
:option:`--copy-cmdline <launch --copy-cmdline>`, :option:`--copy-env <launch :option:`--copy-cmdline <launch --copy-cmdline>`, :option:`--copy-env <launch
@@ -314,7 +314,8 @@ window, etc. Not all arguments are supported, see the discussion in the
In order to avoid remote code execution, kitty will only execute the configured In order to avoid remote code execution, kitty will only execute the configured
editor and pass the file path to edit to it and it will strip all environment editor and pass the file path to edit to it and it will strip all environment
variables from the :command:`edit-in-kitty` command line. variables from the :command:`edit-in-kitty` command line. Additionally, parsing
of colors is more limited, reading colors from config files is not allowed.
.. note:: To edit files using sudo the best method is to set the .. note:: To edit files using sudo the best method is to set the
:code:`SUDO_EDITOR` environment variable to ``kitten edit-in-kitty`` and :code:`SUDO_EDITOR` environment variable to ``kitten edit-in-kitty`` and

View File

@@ -212,6 +212,7 @@ def parse_colors(
if isinstance(spec, str): if isinstance(spec, str):
k, sep, v = spec.partition('=') k, sep, v = spec.partition('=')
if sep == '=': if sep == '=':
k, v = k.strip(), v.strip()
if k in allowed: if k in allowed:
parse_conf_item(k, v, conf) parse_conf_item(k, v, conf)
elif allow_reading_conf_files: elif allow_reading_conf_files:

View File

@@ -869,18 +869,24 @@ def launch(
@run_once @run_once
def clone_safe_opts() -> frozenset[str]: def clone_safe_opts() -> frozenset[str]:
return frozenset(( return frozenset((
'window_title', 'tab_title', 'type', 'keep_focus', 'cwd', 'env', 'var', 'hold', 'window_title', 'tab_title', 'type', 'keep_focus', 'cwd', 'var', 'hold',
'location', 'os_window_class', 'os_window_name', 'os_window_title', 'os_window_state', 'location', 'os_window_class', 'os_window_name', 'os_window_title', 'os_window_state',
'logo', 'logo_position', 'logo_alpha', 'color', 'spacing', 'next_to', 'hold_after_ssh' 'logo', 'logo_position', 'logo_alpha', 'spacing', 'next_to', 'hold_after_ssh'
)) ))
def parse_opts_for_clone(args: list[str]) -> tuple[LaunchCLIOptions, list[str]]: def parse_opts_for_clone(args: list[str], allow_env: bool = False) -> tuple[LaunchCLIOptions, list[str]]:
unsafe, unsafe_args = parse_launch_args(args) unsafe, unsafe_args = parse_launch_args(args)
default_opts, default_args = parse_launch_args() default_opts, default_args = parse_launch_args()
# only copy safe options, those that dont lead to local code exec # only copy safe options, those that dont lead to local code exec
for x in clone_safe_opts(): for x in clone_safe_opts():
setattr(default_opts, x, getattr(unsafe, x)) setattr(default_opts, x, getattr(unsafe, x))
if allow_env:
# Env is not safe in general because some programs may execute code
# based on the value of env vars, such as VIMINIT for vim.
default_opts.env = unsafe.env
# color specs that dont have = will be parsed as a conf file. That is unsafe because of geninclude.
default_opts.color = [x for x in unsafe.color if '=' in x]
return default_opts, unsafe_args return default_opts, unsafe_args
@@ -1074,7 +1080,7 @@ class CloneCmd:
self.bash_version = '' self.bash_version = ''
self.history = '' self.history = ''
self.parse_message(msg) self.parse_message(msg)
self.opts = parse_opts_for_clone(self.args)[0] self.opts = parse_opts_for_clone(self.args, allow_env=True)[0]
def parse_message(self, msg: str) -> None: def parse_message(self, msg: str) -> None:
simple = 'pid', 'envfmt', 'shell', 'bash_version' simple = 'pid', 'envfmt', 'shell', 'bash_version'
@@ -1111,9 +1117,6 @@ def remote_edit(msg: str, window: Window) -> None:
return return
cmdline = get_editor(path_to_edit=c.file_localpath, line_number=c.line_number) cmdline = get_editor(path_to_edit=c.file_localpath, line_number=c.line_number)
c.opts.source_window = c.opts.next_to = f'id:{window.id}' c.opts.source_window = c.opts.next_to = f'id:{window.id}'
# We ignore env vars as some editors execute code present in env vars such as VIMINIT
c.opts.env = ()
c.opts.copy_env = False
w = launch(get_boss(), c.opts, cmdline) w = launch(get_boss(), c.opts, cmdline)
if w is not None: if w is not None:
c.source_window_id = window.id c.source_window_id = window.id