Package: release.debian.org
Severity: normal
Tags: trixie
X-Debbugs-Cc: [email protected]
Control: affects -1 + src:xiphos
User: [email protected]
Usertags: pu

[ Reason ]
Fix CVE-2026-79079.

[ Impact ]
A local attacker can execute arbitrary code via this vulnerability.

[ Tests ]
Compilation is okay. The software runs as usual.

[ Risks ]
The included patch is from upstream and applies cleanly.
popen() is replaced with a safeer alternative.

[ Checklist ]
  [x] *all* changes are documented in the d/changelog
  [x] I reviewed all changes and I approve them
  [x] attach debdiff against the package in (old)stable
  [x] the issue is verified as fixed in unstable

[ Changes ]
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.                                              
                                                                                
                                                                                
                                                 
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 17:42:46.000000000 +0200
+++ xiphos-4.3.2+dfsg1/debian/changelog 2026-10-03 22:05:37.000000000 +0200
@@ -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 <[email protected]>  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 
01:00:00.000000000 +0100
+++ xiphos-4.3.2+dfsg1/debian/patches/0002-CVE-2026-79079.patch 2026-10-03 
22:04:39.000000000 +0200
@@ -0,0 +1,182 @@
+Origin: upstream, f96ad3273277e7fb24908b40f3aa1e9efeeb4e85
+From: Luke <[email protected]>
+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 <[email protected]>
+---
+ 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 17:39:14.000000000 
+0200
+++ xiphos-4.3.2+dfsg1/debian/patches/series    2026-10-03 22:05:14.000000000 
+0200
@@ -1,2 +1,3 @@
 0001-Override-git-version.patch
+0002-CVE-2026-79079.patch
 0003-CMake-Don-t-include-win32.patch

Reply via email to