osc: add option to disable OSC-52, partially or fully

Closes #1867
This commit is contained in:
Daniel Eklöf 2024-12-21 06:52:00 +01:00
parent 67bd5dd460
commit e38ec79be1
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
7 changed files with 99 additions and 1 deletions

View file

@ -64,6 +64,9 @@
* Box drawing characters U+1CD00...U+1CDE5 (the _"octants"_ from the * Box drawing characters U+1CD00...U+1CDE5 (the _"octants"_ from the
_"Symbols for Legacy Computing Supplement"_ codepoint range, added _"Symbols for Legacy Computing Supplement"_ codepoint range, added
in Unicode 16.0). in Unicode 16.0).
* `security.osc52` option, allowing you to partially or fully disable
host clipboard access via the OSC-52 escape sequence
([#1867][1867]).
### Changed ### Changed

View file

@ -1110,6 +1110,25 @@ parse_section_main(struct context *ctx)
} }
} }
static bool
parse_section_security(struct context *ctx)
{
struct config *conf = ctx->conf;
const char *key = ctx->key;
if (streq(key, "osc52")) {
_Static_assert(sizeof(conf->security.osc52) == sizeof(int),
"enum is not 32-bit");
return value_to_enum(
ctx,
(const char *[]){"disabled", "copy-enabled", "paste-enabled", "enabled", NULL},
(int *)&conf->security.osc52);
} else {
LOG_CONTEXTUAL_ERR("not a valid option: %s", key);
return false;
}
}
static bool static bool
parse_section_bell(struct context *ctx) parse_section_bell(struct context *ctx)
{ {
@ -2742,6 +2761,7 @@ parse_key_value(char *kv, const char **section, const char **key, const char **v
enum section { enum section {
SECTION_MAIN, SECTION_MAIN,
SECTION_SECURITY,
SECTION_BELL, SECTION_BELL,
SECTION_DESKTOP_NOTIFICATIONS, SECTION_DESKTOP_NOTIFICATIONS,
SECTION_SCROLLBACK, SECTION_SCROLLBACK,
@ -2769,6 +2789,7 @@ static const struct {
const char *name; const char *name;
} section_info[] = { } section_info[] = {
[SECTION_MAIN] = {&parse_section_main, "main"}, [SECTION_MAIN] = {&parse_section_main, "main"},
[SECTION_SECURITY] = {&parse_section_security, "security"},
[SECTION_BELL] = {&parse_section_bell, "bell"}, [SECTION_BELL] = {&parse_section_bell, "bell"},
[SECTION_DESKTOP_NOTIFICATIONS] = {&parse_section_desktop_notifications, "desktop-notifications"}, [SECTION_DESKTOP_NOTIFICATIONS] = {&parse_section_desktop_notifications, "desktop-notifications"},
[SECTION_SCROLLBACK] = {&parse_section_scrollback, "scrollback"}, [SECTION_SCROLLBACK] = {&parse_section_scrollback, "scrollback"},
@ -3154,6 +3175,9 @@ config_load(struct config *conf, const char *conf_path,
.underline_thickness = {.pt = 0., .px = -1}, .underline_thickness = {.pt = 0., .px = -1},
.strikeout_thickness = {.pt = 0., .px = -1}, .strikeout_thickness = {.pt = 0., .px = -1},
.dpi_aware = false, .dpi_aware = false,
.security = {
.osc52 = OSC52_ENABLED,
},
.bell = { .bell = {
.urgent = false, .urgent = false,
.notify = false, .notify = false,

View file

@ -173,6 +173,15 @@ struct config {
bool box_drawings_uses_font_glyphs; bool box_drawings_uses_font_glyphs;
bool can_shape_grapheme; bool can_shape_grapheme;
struct {
enum {
OSC52_DISABLED,
OSC52_COPY_ENABLED,
OSC52_PASTE_ENABLED,
OSC52_ENABLED,
} osc52;
} security;
struct { struct {
bool urgent; bool urgent;
bool notify; bool notify;

View file

@ -416,6 +416,33 @@ The format is simply:
Note: do not set *TERM* here; use the *term* option in the main Note: do not set *TERM* here; use the *term* option in the main
(default) section instead. (default) section instead.
# SECTION: security
*osc52*
Whether OSC-52 (clipboard access) is enabled or disabled. One of
*disabled*, *copy-enabled*, *paste-enabled* or *enabled*.
OSC-52 gives terminal application access to the host clipboard
(i.e. the Wayland clipboard). This is normally not a security
issue, since all applications can access the clipboard directly
over the Wayland socket.
However, when SSH:ing into a remote system, or accessing a
container etc, the terminal applications may be untrusted, and you
might consider disabling the host clipboard access.
- *disabled*: disables all clipboard access
- *copy-enabled*: applications can write to the clipboard, but not
read from it.
- *paste-enabled*: applications can read from the clipboard, but
not write to it.
- *enabled*: all applications have full access to the host
clipboard. This is the default.
Default: _enabled_
# SECTION: bell # SECTION: bell
*urgent* *urgent*

View file

@ -41,6 +41,9 @@
[environment] [environment]
# name=value # name=value
[security]
# osc52=enabled # disabled|copy-enabled|paste-enabled|enabled
[bell] [bell]
# urgent=no # urgent=no
# notify=no # notify=no

17
osc.c
View file

@ -8,7 +8,7 @@
#include <sys/epoll.h> #include <sys/epoll.h>
#define LOG_MODULE "osc" #define LOG_MODULE "osc"
#define LOG_ENABLE_DBG 0 #define LOG_ENABLE_DBG 1
#include "log.h" #include "log.h"
#include "base64.h" #include "base64.h"
#include "config.h" #include "config.h"
@ -64,6 +64,14 @@ osc_to_clipboard(struct terminal *term, const char *target,
return; return;
} }
const bool copy_allowed = term->conf->security.osc52 == OSC52_ENABLED
|| term->conf->security.osc52 == OSC52_COPY_ENABLED;
if (!copy_allowed) {
LOG_DBG("ignoring copy request: disabled in configuration");
return;
}
char *decoded = base64_decode(base64_data, NULL); char *decoded = base64_decode(base64_data, NULL);
if (decoded == NULL) { if (decoded == NULL) {
if (errno == EINVAL) if (errno == EINVAL)
@ -190,6 +198,13 @@ osc_from_clipboard(struct terminal *term, const char *source)
return; return;
} }
const bool paste_allowed = term->conf->security.osc52 == OSC52_ENABLED
|| term->conf->security.osc52 == OSC52_PASTE_ENABLED;
if (!paste_allowed) {
LOG_DBG("ignoring paste request: disabled in configuration");
return;
}
/* Use clipboard if no source has been specified */ /* Use clipboard if no source has been specified */
char src = source[0] == '\0' ? 'c' : 0; char src = source[0] == '\0' ? 'c' : 0;
bool from_clipboard = src == 'c'; bool from_clipboard = src == 'c';

View file

@ -553,6 +553,22 @@ test_section_main(void)
config_free(&conf); config_free(&conf);
} }
static void
test_section_security(void)
{
struct config conf = {0};
struct context ctx = {.conf = &conf, .section = "security", .path = "unittest"};
test_invalid_key(&ctx, &parse_section_security, "invalid-key");
test_enum(
&ctx, &parse_section_security, "osc52", 4,
(const char*[]){"disabled", "copy-enabled", "paste-enabled", "enabled"},
(int []){OSC52_DISABLED, OSC52_COPY_ENABLED, OSC52_PASTE_ENABLED, OSC52_ENABLED},
(int *)&conf.security.osc52);
config_free(&conf);
}
static void static void
test_section_bell(void) test_section_bell(void)
{ {
@ -1407,6 +1423,7 @@ main(int argc, const char *const *argv)
FcInit(); FcInit();
log_init(LOG_COLORIZE_AUTO, false, 0, LOG_CLASS_ERROR); log_init(LOG_COLORIZE_AUTO, false, 0, LOG_CLASS_ERROR);
test_section_main(); test_section_main();
test_section_security();
test_section_bell(); test_section_bell();
test_section_desktop_notifications(); test_section_desktop_notifications();
test_section_scrollback(); test_section_scrollback();