Blob Blame History Raw
diff --git a/docs/file-transfer-protocol.rst b/docs/file-transfer-protocol.rst
index 783437e9f..86e64fa79 100644
--- a/docs/file-transfer-protocol.rst
+++ b/docs/file-transfer-protocol.rst
@@ -508,7 +508,7 @@ enum
         ac=file
 
 safe_string
-    A string consisting only of characters from the set ``[0-9a-zA-Z_:.,/!@#$%^&*()[]{}~`?"'\\|=+-]``
+    A string consisting only of characters from the set ``[0-9a-zA-Z_:./@-]``
     Note that the semi-colon is missing from this set.
 
 integer
diff --git a/kitty/file_transmission.py b/kitty/file_transmission.py
index 2b9acfe25..78f7ce9e8 100644
--- a/kitty/file_transmission.py
+++ b/kitty/file_transmission.py
@@ -3,6 +3,7 @@
 
 import errno
 import os
+import re
 import stat
 import tempfile
 from base64 import standard_b64decode, standard_b64encode
@@ -30,7 +31,7 @@
 )
 from kitty.types import run_once
 
-from .utils import log_error, sanitize_control_codes
+from .utils import log_error
 
 EXPIRE_TIME = 10  # minutes
 MAX_ACTIVE_RECEIVES = MAX_ACTIVE_SENDS = 10
@@ -41,6 +42,14 @@ def escape_semicolons(x: str) -> str:
     return x.replace(';', ';;')
 
 
+def safe_string_pat() -> 're.Pattern[str]':
+    return re.compile(r'[^0-9a-zA-Z_:./@-]')
+
+
+def safe_string(x: str) -> str:
+    return safe_string_pat().sub('', x)
+
+
 def as_unicode(x: Union[str, bytes]) -> str:
     if isinstance(x, bytes):
         x = x.decode('ascii')
@@ -316,7 +325,7 @@ def get_serialized_fields(self, prefix_with_osc_code: bool = False) -> Iterator[
                 if k.metadata.get('base64'):
                     yield standard_b64encode(val.encode('utf-8'))
                 else:
-                    yield escape_semicolons(sanitize_control_codes(val))
+                    yield escape_semicolons(safe_string(val))
             elif k.type is int:
                 yield str(val)
             else:
@@ -348,7 +357,7 @@ def handle_item(key: memoryview, val: memoryview, has_semicolons: bool) -> None:
                     sval = decode_utf8_buffer(val)
                     if has_semicolons:
                         sval = sval.replace(';;', ';')
-                setattr(ans, field.name, sanitize_control_codes(sval))
+                setattr(ans, field.name, safe_string(sval))
 
         parse_ftc(data, handle_item)
         if ans.action is Action.invalid:
diff --git a/kitty/screen.c b/kitty/screen.c
index 7b9102ff6..3a573e50d 100644
--- a/kitty/screen.c
+++ b/kitty/screen.c
@@ -2160,7 +2160,7 @@ screen_request_capabilities(Screen *self, char c, PyObject *q) {
             } else if (strcmp("r", query) == 0) {
                 shape = snprintf(buf, sizeof(buf), "1$r%u;%ur", self->margin_top + 1, self->margin_bottom + 1);
             } else {
-                shape = snprintf(buf, sizeof(buf), "0$r%s", query);
+                shape = snprintf(buf, sizeof(buf), "0$r");
             }
             if (shape > 0) write_escape_code_to_child(self, DCS, buf);
             break;