From 40f8661d5afe86c7621da81c3b7d6c42ed367bf5 Mon Sep 17 00:00:00 2001 From: Devon Kirk Date: Thu, 18 Jun 2026 16:18:50 -0400 Subject: [PATCH] fix: escape HTML content before embedding in JavaScript string in editor_insert_html editor_insert_html() embeds user-controlled HTML (e.g. the link text from the link dialog) into a JavaScript string literal that is then executed via webkit_web_view_execute_script(): document.execCommand('insertHTML', null, '%s'); Neither single quotes nor backslashes were escaped, so a single quote in the input broke out of the JS string and allowed arbitrary script execution in the editor's WebKit context. Escape the content with g_strescape() before embedding. g_strescape() escapes backslashes, double quotes and control characters, but it does NOT escape single quotes -- so the JS string literal is changed from single-quoted to double-quoted to match what g_strescape() actually escapes. This blocks both ' and " breakout while preserving legitimate HTML markup (e.g. quoted href attributes). --- src/editor/editor.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/editor/editor.c b/src/editor/editor.c index 914eb7ff3..a0e75cd60 100644 --- a/src/editor/editor.c +++ b/src/editor/editor.c @@ -346,10 +346,18 @@ void editor_execute_script(gchar *script, EDITOR *e) void editor_insert_html(const gchar *html, EDITOR *e) { - gchar *str = g_strdup_printf("document.execCommand('insertHTML', null, \'%s\');", html); + /* The HTML is embedded into a JavaScript string literal that is then + executed. g_strescape() escapes backslashes and double quotes (and + control characters), so embed the result inside a *double*-quoted JS + string. Note: g_strescape() does NOT escape single quotes, so the + string literal below must not be single-quoted, or a single quote in + the input would break out and allow script injection. */ + gchar *escaped = g_strescape(html, NULL); + gchar *str = g_strdup_printf("document.execCommand('insertHTML', null, \"%s\");", escaped); XI_message(("script: %s", str)); editor_execute_script(str, e); g_free(str); + g_free(escaped); } /*