From 1c971ade6531c7dd9ac872409a36903466ff1bf3 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 21 Sep 2026 00:10:07 +0200 Subject: [PATCH 1/5] networkmanager-libreswan: init at 1.2.31 This is a IPsec IKEv1 VPN, Cisco compatible plug-in maintained by the NetworkManager maintainers. https://gitlab.gnome.org/GNOME/NetworkManager-libreswan As per https://networkmanager.dev/docs/vpn/ and https://blogs.gnome.org/mcatanzaro/2026/09/15/privilege-escalation-vulnerabilities-in-networkmanager-plugins/ this is a replacement for the insecure and unmaintained NetworkManager-vpnc but connection profiles have to be recreated and per-option parity has not been checked. (cherry picked from commit 5310b2ae1f5b5eb1107b43c2d490387d2daaffa5) --- .../services/networking/networkmanager.nix | 1 + .../networkmanager-libreswan/fix-paths.patch | 48 +++++++++++ .../ne/networkmanager-libreswan/package.nix | 85 +++++++++++++++++++ 3 files changed, 134 insertions(+) create mode 100644 pkgs/by-name/ne/networkmanager-libreswan/fix-paths.patch create mode 100644 pkgs/by-name/ne/networkmanager-libreswan/package.nix diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 2cb3532471c8..7f9702a42f7e 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -240,6 +240,7 @@ in with pkgs; [ networkmanager-fortisslvpn networkmanager-iodine + networkmanager-libreswan networkmanager-l2tp networkmanager-openconnect networkmanager-openvpn diff --git a/pkgs/by-name/ne/networkmanager-libreswan/fix-paths.patch b/pkgs/by-name/ne/networkmanager-libreswan/fix-paths.patch new file mode 100644 index 000000000000..eeccde58a696 --- /dev/null +++ b/pkgs/by-name/ne/networkmanager-libreswan/fix-paths.patch @@ -0,0 +1,48 @@ +diff --git a/properties/nm-libreswan-editor-plugin.c b/properties/nm-libreswan-editor-plugin.c +index 6a178af..787e183 100644 +--- a/properties/nm-libreswan-editor-plugin.c ++++ b/properties/nm-libreswan-editor-plugin.c +@@ -96,7 +96,7 @@ export_to_file(NMVpnEditorPlugin *self, const char *path, NMConnection *connecti + + openswan = nm_streq(nm_setting_vpn_get_service_type(s_vpn), NM_VPN_SERVICE_TYPE_OPENSWAN); + +- nm_libreswan_detect_version(nm_libreswan_find_helper_bin("ipsec", NULL), ++ nm_libreswan_detect_version("@ipsec@", + &is_openswan, + &version, + NULL); +diff --git a/src/nm-libreswan-service.c b/src/nm-libreswan-service.c +index 0458d4e..e0add02 100644 +--- a/src/nm-libreswan-service.c ++++ b/src/nm-libreswan-service.c +@@ -1820,7 +1820,7 @@ connect_step(NMLibreswanPlugin *self, GError **error) + if (!priv->openswan) { + const char *stackman_path; + +- stackman_path = nm_libreswan_find_helper_libexec("_stackmanager", error); ++ stackman_path = "@libreswan@/libexec/_stackmanager"; + if (!stackman_path) + return FALSE; + +@@ -1977,7 +1977,7 @@ _connect_common(NMVpnServicePlugin *plugin, + return FALSE; + } + +- priv->ipsec_path = nm_libreswan_find_helper_bin("ipsec", error); ++ priv->ipsec_path = "@ipsec@"; + if (!priv->ipsec_path) + return FALSE; + +@@ -1988,10 +1988,10 @@ _connect_common(NMVpnServicePlugin *plugin, + priv->openswan ? "Openswan" : "Libreswan"); + + if (!priv->openswan) { +- priv->pluto_path = nm_libreswan_find_helper_libexec("pluto", error); ++ priv->pluto_path = "@libreswan@/libexec/pluto"; + if (!priv->pluto_path) + return FALSE; +- priv->whack_path = nm_libreswan_find_helper_libexec("whack", error); ++ priv->whack_path = "@libreswan@/libexec/whack"; + if (!priv->whack_path) + return FALSE; + } diff --git a/pkgs/by-name/ne/networkmanager-libreswan/package.nix b/pkgs/by-name/ne/networkmanager-libreswan/package.nix new file mode 100644 index 000000000000..f59beee648d8 --- /dev/null +++ b/pkgs/by-name/ne/networkmanager-libreswan/package.nix @@ -0,0 +1,85 @@ +{ + dieHook, + fetchpatch, + fetchurl, + glib, + gnome, + gtk3, + gtk4, + intltool, + lib, + libnl, + libnma, + libnma-gtk4, + libreswan, + libsecret, + networkmanager, + pkg-config, + replaceVars, + stdenv, + withGnome ? true, +}: + +stdenv.mkDerivation (finalAttrs: { + pname = "NetworkManager-libreswan"; + version = "1.2.31"; + + src = fetchurl { + url = "mirror://gnome/sources/NetworkManager-libreswan/${lib.versions.majorMinor finalAttrs.version}/NetworkManager-libreswan-${finalAttrs.version}.tar.xz"; + hash = "sha256-5xq3zWruZoOqlDQusm5hQzv/3y2ml4LsptHCmdzDp28="; + }; + + patches = [ + (replaceVars ./fix-paths.patch { + ipsec = lib.getExe' libreswan "ipsec"; + inherit libreswan; + }) + ]; + + nativeBuildInputs = [ + dieHook + glib + intltool + pkg-config + ]; + + buildInputs = [ + libnl + networkmanager + ] + ++ lib.optionals withGnome [ + gtk3 + gtk4 + libnma + libnma-gtk4 + libsecret + ]; + + configureFlags = [ + "--with-gnome=${lib.boolToYesNo withGnome}" + "--with-gtk4=${lib.boolToYesNo withGnome}" + "--enable-absolute-paths" + ]; + + strictDeps = true; + __structuredAttrs = true; + + postPatch = '' + echo "Ensuring that all helper paths lookups were replaced" + ! grep -lr nm_libreswan_find_helper --exclude 'utils.[ch]' || die "^ Found non-replaced helper lookup" + ''; + + passthru = { + updateScript = gnome.updateScript { + packageName = "NetworkManager-libreswan"; + attrPath = "networkmanager-libreswan"; + }; + networkManagerPlugin = "VPN/nm-libreswan-service.name"; + }; + + meta = { + description = "NetworkManager's libreswan plugin"; + inherit (networkmanager.meta) maintainers teams platforms; + license = lib.licenses.gpl2Plus; + }; +}) From c58899ee01363db8859d0892a76413252a9b8b67 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 21 Sep 2026 00:50:56 +0200 Subject: [PATCH 2/5] networkmanager-vpnc: Mark as vulnerable https://blogs.gnome.org/mcatanzaro/2026/09/15/privilege-escalation-vulnerabilities-in-networkmanager-plugins/ https://gitlab.gnome.org/GNOME/NetworkManager-vpnc/-/work_items/19 https://gitlab.gnome.org/GNOME/NetworkManager-vpnc/-/work_items/20 Also stop recommending it in NM NixOS module docs. (cherry picked from commit b4b3300c9f7df642b2f9746cff22848f8123be1e) --- nixos/modules/services/networking/networkmanager.nix | 1 - pkgs/by-name/ne/networkmanager-vpnc/package.nix | 4 ++++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 7f9702a42f7e..5bd556e9570c 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -246,7 +246,6 @@ in networkmanager-openvpn networkmanager-sstp networkmanager-strongswan - networkmanager-vpnc ] ''; description = '' diff --git a/pkgs/by-name/ne/networkmanager-vpnc/package.nix b/pkgs/by-name/ne/networkmanager-vpnc/package.nix index c3ec042cf249..96ea11667433 100644 --- a/pkgs/by-name/ne/networkmanager-vpnc/package.nix +++ b/pkgs/by-name/ne/networkmanager-vpnc/package.nix @@ -70,6 +70,10 @@ stdenv.mkDerivation rec { meta = { description = "NetworkManager's VPNC plugin"; + knownVulnerabilities = [ + "CVE-2026-91840" + "CVE-2026-91841" + ]; inherit (networkmanager.meta) maintainers teams platforms; license = lib.licenses.gpl2Plus; }; From d03a16006cc2324b59a031322850879428b518b6 Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 21 Sep 2026 00:52:48 +0200 Subject: [PATCH 3/5] networkmanager-fortisslvpn: Mark as vulnerable https://blogs.gnome.org/mcatanzaro/2026/09/15/privilege-escalation-vulnerabilities-in-networkmanager-plugins/ https://gitlab.gnome.org/GNOME/NetworkManager-fortisslvpn/-/work_items/80 Also stop recommending it in NM NixOS module docs. (cherry picked from commit 85b6f5ef108dc2f00d043162ff4466755a4de146) --- nixos/modules/services/networking/networkmanager.nix | 1 - pkgs/by-name/ne/networkmanager-fortisslvpn/package.nix | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/nixos/modules/services/networking/networkmanager.nix b/nixos/modules/services/networking/networkmanager.nix index 5bd556e9570c..17252087c4b9 100644 --- a/nixos/modules/services/networking/networkmanager.nix +++ b/nixos/modules/services/networking/networkmanager.nix @@ -238,7 +238,6 @@ in default = [ ]; example = literalExpression '' with pkgs; [ - networkmanager-fortisslvpn networkmanager-iodine networkmanager-libreswan networkmanager-l2tp diff --git a/pkgs/by-name/ne/networkmanager-fortisslvpn/package.nix b/pkgs/by-name/ne/networkmanager-fortisslvpn/package.nix index 737d3ce60d61..af15e3808d1a 100644 --- a/pkgs/by-name/ne/networkmanager-fortisslvpn/package.nix +++ b/pkgs/by-name/ne/networkmanager-fortisslvpn/package.nix @@ -90,6 +90,9 @@ stdenv.mkDerivation rec { meta = { description = "NetworkManager’s FortiSSL plugin"; inherit (networkmanager.meta) maintainers teams platforms; + knownVulnerabilities = [ + "CVE-2026-91839" + ]; license = lib.licenses.gpl2Plus; }; } From 26fa5cd1cdc8be4fbd4eb60c34a51c3196d3595a Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 21 Sep 2026 00:23:19 +0200 Subject: [PATCH 4/5] networkmanager-sstp: Mark as vulnerable to CVE-2026-91837 https://blogs.gnome.org/mcatanzaro/2026/09/15/privilege-escalation-vulnerabilities-in-networkmanager-plugins/ Unmaintained upstream and no patch currently available: https://gitlab.gnome.org/GNOME/network-manager-sstp/-/work_items/67 (cherry picked from commit 8eced6a02d4119f938c3bb792b2ed9c59a494b10) --- pkgs/by-name/ne/networkmanager-sstp/package.nix | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkgs/by-name/ne/networkmanager-sstp/package.nix b/pkgs/by-name/ne/networkmanager-sstp/package.nix index 42df1b088fa8..e394ba6ba658 100644 --- a/pkgs/by-name/ne/networkmanager-sstp/package.nix +++ b/pkgs/by-name/ne/networkmanager-sstp/package.nix @@ -78,6 +78,9 @@ stdenv.mkDerivation rec { meta = { description = "NetworkManager's sstp plugin"; inherit (networkmanager.meta) maintainers teams platforms; + knownVulnerabilities = [ + "CVE-2026-91838" + ]; license = lib.licenses.gpl2Plus; }; } From 21adc2a082d791e1513bc8b83539dfc418e7c3fb Mon Sep 17 00:00:00 2001 From: Jan Tojnar Date: Mon, 21 Sep 2026 00:32:54 +0200 Subject: [PATCH 5/5] networkmanager-iodine: Apply patch for CVE-2026-91837 https://blogs.gnome.org/mcatanzaro/2026/09/15/privilege-escalation-vulnerabilities-in-networkmanager-plugins/ (cherry picked from commit e52d50d1e1001145b7c18278feb42969b8c759fe) --- .../CVE-2026-91837.patch | 203 ++++++++++++++++++ .../ne/networkmanager-iodine/package.nix | 4 + 2 files changed, 207 insertions(+) create mode 100644 pkgs/by-name/ne/networkmanager-iodine/CVE-2026-91837.patch diff --git a/pkgs/by-name/ne/networkmanager-iodine/CVE-2026-91837.patch b/pkgs/by-name/ne/networkmanager-iodine/CVE-2026-91837.patch new file mode 100644 index 000000000000..97f786814930 --- /dev/null +++ b/pkgs/by-name/ne/networkmanager-iodine/CVE-2026-91837.patch @@ -0,0 +1,203 @@ +diff --git a/src/nm-iodine-service.c b/src/nm-iodine-service.c +index 75a1610e4281588336985636a2dd4eda03575d3a..2cc74f6859304a895be0080dd50f72ddd29a8219 100644 +--- a/src/nm-iodine-service.c ++++ b/src/nm-iodine-service.c +@@ -468,14 +468,58 @@ send_password(gint fd, NMSettingVpn *s_vpn) + } + + +-static gint ++static gboolean ++label_is_valid (const gchar *label, gsize len) ++{ ++ if (len == 0 || len > 63) ++ return FALSE; ++ if (label[0] == '-' || label[len - 1] == '-') ++ return FALSE; ++ for (gsize i = 0; i < len; i++) ++ if (!g_ascii_isalnum (label[i]) && label[i] != '-') ++ return FALSE; ++ return TRUE; ++} ++ ++ ++static gboolean ++domain_is_valid (const gchar *domain) ++{ ++ g_autofree char *ascii = NULL; ++ g_auto (GStrv) labels = NULL; ++ ++ if (domain == NULL || *domain == '\0') ++ return FALSE; ++ ++ /* Normalizes IDN labels to punycode; NULL on malformed UTF-8/encoding */ ++ ascii = g_hostname_to_ascii (domain); ++ if (ascii == NULL) ++ return FALSE; ++ ++ if (strlen (ascii) > 253) ++ return FALSE; ++ ++ labels = g_strsplit (ascii, ".", -1); ++ if (labels == NULL || labels[0] == NULL || labels[1] == NULL) ++ return FALSE; ++ ++ for (int i = 0; labels[i] != NULL; i++) { ++ if (!label_is_valid (labels[i], -1)) ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++ ++static gboolean + nm_iodine_start_iodine_binary (NMIodinePlugin *plugin, + NMSettingVpn *s_vpn, + GError **error) + { + GPid pid; + const char **iodine_binary = NULL; +- GPtrArray *iodine_argv; ++ g_autoptr (GPtrArray) iodine_argv = g_ptr_array_new_full (12, NULL); + GSource *iodine_watch; + GIOChannel *stderr_channel; + gint stdin_fd, stderr_fd; +@@ -491,27 +535,20 @@ nm_iodine_start_iodine_binary (NMIodinePlugin *plugin, + } + + if (!*iodine_binary) { +- g_set_error (error, +- NM_VPN_PLUGIN_ERROR, +- NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, +- "%s", +- _("Could not find iodine binary.")); +- return -1; ++ g_set_error_literal (error, ++ NM_VPN_PLUGIN_ERROR, ++ NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, ++ _("Could not find iodine binary.")); ++ return FALSE; + } + + props_fragsize = nm_setting_vpn_get_data_item (s_vpn, NM_IODINE_KEY_FRAGSIZE); + props_nameserver = nm_setting_vpn_get_data_item (s_vpn, NM_IODINE_KEY_NAMESERVER); + props_topdomain = nm_setting_vpn_get_data_item (s_vpn, NM_IODINE_KEY_TOPDOMAIN); +- iodine_argv = g_ptr_array_new (); + g_ptr_array_add (iodine_argv, (gpointer) (*iodine_binary)); + /* Run in foreground */ + g_ptr_array_add (iodine_argv, (gpointer) "-f"); + +- if (props_fragsize && strlen(props_fragsize)) { +- g_ptr_array_add (iodine_argv, (gpointer) "-m"); +- g_ptr_array_add (iodine_argv, (gpointer) props_fragsize); +- } +- + if (has_user(NM_IODINE_USER)) { + g_ptr_array_add (iodine_argv, (gpointer) "-u"); + g_ptr_array_add (iodine_argv, (gpointer) NM_IODINE_USER); +@@ -524,11 +561,51 @@ nm_iodine_start_iodine_binary (NMIodinePlugin *plugin, + } else + g_warning("Not running chrooted"); + +- if (props_nameserver && strlen(props_nameserver)) +- g_ptr_array_add (iodine_argv, (gpointer) props_nameserver); ++ if (props_fragsize && strlen(props_fragsize)) { ++ gchar *end = NULL; + +- if (props_topdomain && strlen(props_topdomain)) +- g_ptr_array_add (iodine_argv, (gpointer) props_topdomain); ++ (void)g_ascii_strtoll(props_fragsize, &end, 10); ++ if (end != props_fragsize || *end == '\0') { ++ g_ptr_array_add (iodine_argv, (gpointer) "-m"); ++ g_ptr_array_add (iodine_argv, (gpointer) props_fragsize); ++ } else { ++ g_warning("Failed to parse fragment size"); ++ g_set_error (error, ++ NM_VPN_PLUGIN_ERROR, ++ NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, ++ _("Invalid fragment size '%s'"), ++ props_fragsize); ++ return FALSE; ++ } ++ } ++ ++ if (props_nameserver && strlen(props_nameserver)) { ++ g_autoptr (GInetAddress) addr = g_inet_address_new_from_string (props_nameserver); ++ ++ if (addr) { ++ g_ptr_array_add (iodine_argv, (gpointer) props_nameserver); ++ } else { ++ g_set_error (error, ++ NM_VPN_PLUGIN_ERROR, ++ NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, ++ _("Invalid nameserver '%s'"), ++ props_nameserver); ++ return FALSE; ++ } ++ } ++ ++ if (props_topdomain && strlen(props_topdomain)) { ++ if (domain_is_valid (props_topdomain)) ++ g_ptr_array_add (iodine_argv, (gpointer) props_topdomain); ++ else { ++ g_set_error (error, ++ NM_VPN_PLUGIN_ERROR, ++ NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED, ++ _("Invalid domain '%s'"), ++ props_topdomain); ++ return FALSE; ++ } ++ } + + g_ptr_array_add (iodine_argv, NULL); + +@@ -536,11 +613,9 @@ nm_iodine_start_iodine_binary (NMIodinePlugin *plugin, + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, + &pid, &stdin_fd, NULL, &stderr_fd, error)) { +- g_ptr_array_free (iodine_argv, TRUE); + g_warning ("iodine failed to start. error: '%s'", (*error)->message); +- return -1; ++ return FALSE; + } +- g_ptr_array_free (iodine_argv, TRUE); + + g_message ("iodine started with pid %d", pid); + +@@ -556,13 +631,13 @@ nm_iodine_start_iodine_binary (NMIodinePlugin *plugin, + priv->pid = pid; + iodine_watch = g_child_watch_source_new (pid); + g_source_set_callback (iodine_watch, +- (GSourceFunc) iodine_watch_cb, ++ G_SOURCE_FUNC (iodine_watch_cb), + plugin, + NULL); + g_source_attach (iodine_watch, NULL); + g_source_unref (iodine_watch); + +- return 0; ++ return TRUE; + } + + static gboolean +@@ -572,7 +647,7 @@ real_connect (NMVpnServicePlugin *plugin, + { + NMSettingVpn *s_vpn; + NMIodinePluginPrivate *priv = nm_iodine_plugin_get_instance_private (NM_IODINE_PLUGIN(plugin)); +- gint ret = -1; ++ gboolean success; + + g_variant_builder_init(&priv->ip4config, G_VARIANT_TYPE_VARDICT); + +@@ -584,8 +659,8 @@ real_connect (NMVpnServicePlugin *plugin, + if (!nm_iodine_secrets_validate (s_vpn, error)) + goto out; + +- ret = nm_iodine_start_iodine_binary (NM_IODINE_PLUGIN (plugin), s_vpn, error); +- if (!ret) ++ success = nm_iodine_start_iodine_binary (NM_IODINE_PLUGIN (plugin), s_vpn, error); ++ if (success) + return TRUE; + + out: diff --git a/pkgs/by-name/ne/networkmanager-iodine/package.nix b/pkgs/by-name/ne/networkmanager-iodine/package.nix index 1b3e6fc95564..1574a8bf79ca 100644 --- a/pkgs/by-name/ne/networkmanager-iodine/package.nix +++ b/pkgs/by-name/ne/networkmanager-iodine/package.nix @@ -32,6 +32,10 @@ stdenv.mkDerivation { (replaceVars ./fix-paths.patch { inherit iodine; }) + + # https://gitlab.gnome.org/GNOME/network-manager-iodine/-/issues/4 + # https://gitlab.gnome.org/GNOME/network-manager-iodine/-/merge_requests/6 + ./CVE-2026-91837.patch ]; nativeBuildInputs = [