Version in base suite: 4.3.2+dfsg1-1 Base version: xiphos_4.3.2+dfsg1-1 Target version: xiphos_4.3.2+dfsg1-1+deb13u1 Base file: /srv/ftp-master.debian.org/ftp/pool/main/x/xiphos/xiphos_4.3.2+dfsg1-1.dsc Target file: /srv/ftp-master.debian.org/policy/pool/main/x/xiphos/xiphos_4.3.2+dfsg1-1+deb13u1.dsc changelog | 7 + patches/0002-CVE-2026-79079.patch | 182 ++++++++++++++++++++++++++++++++++++++ patches/series | 1 3 files changed, 190 insertions(+) dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp3_zemcx4/xiphos_4.3.2+dfsg1-1.dsc: no acceptable signature found dpkg-source: warning: cannot verify inline signature for /srv/release.debian.org/tmp/tmp3_zemcx4/xiphos_4.3.2+dfsg1-1+deb13u1.dsc: no acceptable signature found diff -Nru xiphos-4.3.2+dfsg1/debian/changelog xiphos-4.3.2+dfsg1/debian/changelog --- xiphos-4.3.2+dfsg1/debian/changelog 2025-04-13 15:42:46.000000000 +0000 +++ xiphos-4.3.2+dfsg1/debian/changelog 2026-10-03 20:05:37.000000000 +0000 @@ -1,3 +1,10 @@ +xiphos (4.3.2+dfsg1-1+deb13u1) trixie; urgency=medium + + * Team upload + * Fix CVE-2026-79079 (local arbitrary code execution) + + -- Bastian Germann Sat, 03 Oct 2026 22:05:37 +0200 + xiphos (4.3.2+dfsg1-1) unstable; urgency=high * Team upload diff -Nru xiphos-4.3.2+dfsg1/debian/patches/0002-CVE-2026-79079.patch xiphos-4.3.2+dfsg1/debian/patches/0002-CVE-2026-79079.patch --- xiphos-4.3.2+dfsg1/debian/patches/0002-CVE-2026-79079.patch 1970-01-01 00:00:00.000000000 +0000 +++ xiphos-4.3.2+dfsg1/debian/patches/0002-CVE-2026-79079.patch 2026-10-03 20:05:37.000000000 +0000 @@ -0,0 +1,182 @@ +Origin: upstream, f96ad3273277e7fb24908b40f3aa1e9efeeb4e85 +From: Luke +Date: Fri, 22 May 2026 12:34:32 -0500 +Subject: Fix shell command safety: replace popen() with g_spawn functions (#1314) + +Replace two popen() calls with GLib's g_spawn_async() and g_spawn_sync() +to avoid passing arguments through a shell. This prevents filenames or +other data containing shell metacharacters from being interpreted as +shell commands. + +- src/main/url.cc show_separate_image(): use g_spawn_async() with an + argument array and G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL + flags, matching the original redirect-to-devnull behavior. Report errors + via GError. + +- src/gtk/menu_popup.c on_rename_perscomm_activate(): use g_spawn_sync() + with sed invoked via argument array. Capture stdout and write the result + via g_file_set_contents(). Check exit status and GError. + +Co-authored-by: Luke +--- + src/gtk/menu_popup.c | 85 +++++++++++++++++++++++++++++++++----------- + src/main/url.cc | 32 ++++++----------- + 2 files changed, 76 insertions(+), 41 deletions(-) + +diff --git a/src/gtk/menu_popup.c b/src/gtk/menu_popup.c +index 8154063f3..a6c5af930 100644 +--- a/src/gtk/menu_popup.c ++++ b/src/gtk/menu_popup.c +@@ -1354,7 +1354,6 @@ G_MODULE_EXPORT void on_rename_perscomm_activate(GtkMenuItem *menuitem, + const char *conf_old; + char *conf_new; + char *sworddir, *modsdir; +- FILE *result; + + // get a new name for the module. + info = gui_new_dialog(); +@@ -1415,28 +1414,74 @@ G_MODULE_EXPORT void on_rename_perscomm_activate(GtkMenuItem *menuitem, + goto out2; + } + // manufacture new .conf from old. +- g_string_printf(workstr, +- "( cd \"%s\" && sed -e '/^\\[/s|^.*$|[%s]|' -e '/^DataPath=/s|rawfiles/.*$|rawfiles/%s/|' < \"%s\" > \"%s.conf\" ) 2>&1", +- modsdir, info->text1, conf_new, conf_old, +- conf_new); +- if ((result = popen(workstr->str, "r")) == NULL) { +- g_string_printf(workstr, ++ gchar *conf_path_old = g_strdup_printf("%s/%s", modsdir, conf_old); ++ gchar *conf_path_new = g_strdup_printf("%s/%s.conf", modsdir, conf_new); ++ gchar *sed_old_sec = g_strdup_printf("[%s]", info->text1); ++ gchar *sed_old_path = g_strdup_printf("rawfiles/%s/", conf_new); ++ gchar *sed_expr = g_strdup_printf( ++ "/^\\[/s|^.*$|%s|;/^DataPath=/s|rawfiles/.*$|%s|", ++ sed_old_sec, sed_old_path); ++ gchar *argv[] = { ++ (gchar *)"sed", (gchar *)"-e", sed_expr, conf_path_old, NULL ++ }; ++ GError *spawn_error = NULL; ++ gint exit_status = 0; ++ gchar *spawn_stdout = NULL; ++ gchar *spawn_stderr = NULL; ++ gboolean spawn_ok = g_spawn_sync(modsdir, argv, NULL, ++ G_SPAWN_SEARCH_PATH, ++ NULL, NULL, &spawn_stdout, &spawn_stderr, &exit_status, &spawn_error); ++ if (!spawn_ok) { ++ gchar *msg = g_strdup_printf( + _("Failed to create new configuration:\n%s"), +- strerror(errno)); +- gui_generic_warning_modal(workstr->str); ++ spawn_error ? spawn_error->message : "unknown error"); ++ gui_generic_warning_modal(msg); ++ g_free(msg); ++ if (spawn_error) g_error_free(spawn_error); ++ g_free(conf_path_old); ++ g_free(conf_path_new); ++ g_free(sed_old_sec); ++ g_free(sed_old_path); ++ g_free(sed_expr); ++ g_free(spawn_stdout); ++ g_free(spawn_stderr); ++ goto out2; ++ } ++ if (exit_status != 0) { ++ gchar *msg = g_strdup_printf( ++ _("Configuration build error:\n\n%s"), ++ spawn_stderr ? spawn_stderr : "(no error output)"); ++ gui_generic_warning_modal(msg); ++ g_free(msg); ++ g_free(conf_path_old); ++ g_free(conf_path_new); ++ g_free(sed_old_sec); ++ g_free(sed_old_path); ++ g_free(sed_expr); ++ g_free(spawn_stdout); ++ g_free(spawn_stderr); ++ goto out2; ++ } ++ // Write sed output to the new .conf file. ++ if (!g_file_set_contents(conf_path_new, spawn_stdout ? spawn_stdout : "", ++ spawn_stdout ? strlen(spawn_stdout) : 0, NULL)) { ++ gui_generic_warning_modal("Failed to write new configuration file."); ++ g_free(conf_path_old); ++ g_free(conf_path_new); ++ g_free(sed_old_sec); ++ g_free(sed_old_path); ++ g_free(sed_expr); ++ g_free(spawn_stdout); ++ g_free(spawn_stderr); + goto out2; +- } else { +- gchar output[258]; +- if (fgets(output, 256, result) != NULL) { +- g_string_truncate(workstr, 0); +- g_string_append(workstr, +- _("Configuration build error:\n\n")); +- g_string_append(workstr, output); +- gui_generic_warning_modal(workstr->str); +- goto out2; // necessary? advisable? +- } +- pclose(result); + } ++ g_free(conf_path_old); ++ g_free(conf_path_new); ++ g_free(sed_old_sec); ++ g_free(sed_old_path); ++ g_free(sed_expr); ++ g_free(spawn_stdout); ++ g_free(spawn_stderr); + + // unlink old conf. + g_string_printf(workstr, "%s/%s", modsdir, conf_old); +diff --git a/src/main/url.cc b/src/main/url.cc +index d7081ce4b..92b997783 100644 +--- a/src/main/url.cc ++++ b/src/main/url.cc +@@ -172,8 +172,6 @@ static gint show_separate_image(const gchar *filename, gboolean clicked) + gui_generic_warning((char *)"Could not display that image"); + } + #else +- FILE *result; +- GString *cmd = g_string_new(NULL); + int i; + + for (i = 0; display_progs[i]; i++) { +@@ -186,26 +184,18 @@ static gint show_separate_image(const gchar *filename, gboolean clicked) + } + + XI_print(("file = %s\n", filename)); +- g_string_printf(cmd, "%s \"%s\" < /dev/null > /dev/null 2>&1 &", +- display_progs[i], filename); +- +- if ((result = popen(cmd->str, "r")) == NULL) { +- g_string_printf(cmd, +- _("Xiphos could not execute %s"), +- display_progs[i]); +- gui_generic_warning(cmd->str); +- } else { +- gchar output[258]; +- if (fgets(output, 256, result) != NULL) { +- g_string_truncate(cmd, 0); +- g_string_append(cmd, +- _("Viewer error:\n")); +- g_string_append(cmd, output); +- gui_generic_warning(cmd->str); +- } +- pclose(result); ++ gchar *argv[] = {(gchar *)display_progs[i], (gchar *)filename, NULL}; ++ GError *error = NULL; ++ if (!g_spawn_async(NULL, argv, NULL, ++ (GSpawnFlags)(G_SPAWN_SEARCH_PATH | G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL), ++ NULL, NULL, NULL, &error)) { ++ gchar *msg = g_strdup_printf( ++ _("Xiphos could not execute %s: %s"), ++ display_progs[i], error->message); ++ gui_generic_warning(msg); ++ g_free(msg); ++ g_error_free(error); + } +- g_string_free(cmd, TRUE); + #endif + } else { + gui_set_statusbar(filename); diff -Nru xiphos-4.3.2+dfsg1/debian/patches/series xiphos-4.3.2+dfsg1/debian/patches/series --- xiphos-4.3.2+dfsg1/debian/patches/series 2025-04-13 15:39:14.000000000 +0000 +++ xiphos-4.3.2+dfsg1/debian/patches/series 2026-10-03 20:05:37.000000000 +0000 @@ -1,2 +1,3 @@ 0001-Override-git-version.patch +0002-CVE-2026-79079.patch 0003-CMake-Don-t-include-win32.patch