From eca384e3387cfd7ea0991d68fe39d9bd7e71143b Mon Sep 17 00:00:00 2001
From: Vu Huy Nguyen <26673584+blaccod@users.noreply.github.com>
Date: Sat, 24 Jan 2026 23:58:00 +0100
Subject: [PATCH 1/5] Set full command as default for dangerous binaries
For commands that should not be blanket-allowed like curl or wget, set
the "this command line only" as default target for rules
---
ui/opensnitch/dialogs/prompt/constants.py | 1 +
ui/opensnitch/dialogs/prompt/utils.py | 7 +++++++
2 files changed, 8 insertions(+)
diff --git a/ui/opensnitch/dialogs/prompt/constants.py b/ui/opensnitch/dialogs/prompt/constants.py
index 7ecba064fe..985cedc940 100644
--- a/ui/opensnitch/dialogs/prompt/constants.py
+++ b/ui/opensnitch/dialogs/prompt/constants.py
@@ -39,6 +39,7 @@
APPIMAGE_PREFIX = "/tmp/.mount_"
SNAP_PREFIX = "/snap"
+FULL_COMMAND_BIN = ["python", "curl", "wget", "node", "java"]
# label displayed in the pop-up combo
DURATION_session = QC.translate("popups", "until reboot")
diff --git a/ui/opensnitch/dialogs/prompt/utils.py b/ui/opensnitch/dialogs/prompt/utils.py
index a362748cf9..3dd52c39fd 100644
--- a/ui/opensnitch/dialogs/prompt/utils.py
+++ b/ui/opensnitch/dialogs/prompt/utils.py
@@ -1,6 +1,7 @@
from slugify import slugify
import os
import ipaddress
+from pathlib import Path
from PyQt6.QtCore import QCoreApplication as QC
@@ -230,6 +231,7 @@ def set_default_duration(cfg, durationCombo):
def set_default_target(combo, con, cfg, app_name, app_args):
# set appimage as default target if the process path starts with
# /tmp/._mount
+ connection_path = Path(con.process_path)
if con.process_path.startswith(constants.APPIMAGE_PREFIX):
idx = combo.findData(constants.FIELD_APPIMAGE)
if idx != -1:
@@ -240,6 +242,11 @@ def set_default_target(combo, con, cfg, app_name, app_args):
if idx != -1:
combo.setCurrentIndex(idx)
return
+ # entire command as default target for "dangerous" commands
+ # (e.g. curl, wget, node)
+ elif any(bin in connection_path.name for bin in constants.FULL_COMMAND_BIN):
+ combo.setCurrentIndex(1)
+ return
saved_target = int(cfg.getSettings(cfg.DEFAULT_TARGET_KEY))
# In order to respect user selection, the app_name and app_args must be
From 8a747e8fcd43b9038df859b8a218d79dfc11256c Mon Sep 17 00:00:00 2001
From: Vu Huy Nguyen <26673584+blaccod@users.noreply.github.com>
Date: Sun, 25 Jan 2026 00:05:45 +0100
Subject: [PATCH 2/5] Match using startswith and not in to reduce potential
false positives
---
ui/opensnitch/dialogs/prompt/utils.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/opensnitch/dialogs/prompt/utils.py b/ui/opensnitch/dialogs/prompt/utils.py
index 3dd52c39fd..4f118446df 100644
--- a/ui/opensnitch/dialogs/prompt/utils.py
+++ b/ui/opensnitch/dialogs/prompt/utils.py
@@ -244,7 +244,7 @@ def set_default_target(combo, con, cfg, app_name, app_args):
return
# entire command as default target for "dangerous" commands
# (e.g. curl, wget, node)
- elif any(bin in connection_path.name for bin in constants.FULL_COMMAND_BIN):
+ elif any(connection_path.name.startswith(bin) for bin in constants.FULL_COMMAND_BIN):
combo.setCurrentIndex(1)
return
From 85e8d26040ead6ad02596dad582dfe0667ba10d4 Mon Sep 17 00:00:00 2001
From: Vu Huy Nguyen <26673584+blaccod@users.noreply.github.com>
Date: Sun, 25 Jan 2026 00:09:48 +0100
Subject: [PATCH 3/5] ssh is also dangerous
---
ui/opensnitch/dialogs/prompt/constants.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ui/opensnitch/dialogs/prompt/constants.py b/ui/opensnitch/dialogs/prompt/constants.py
index 985cedc940..b5b75a8361 100644
--- a/ui/opensnitch/dialogs/prompt/constants.py
+++ b/ui/opensnitch/dialogs/prompt/constants.py
@@ -39,7 +39,7 @@
APPIMAGE_PREFIX = "/tmp/.mount_"
SNAP_PREFIX = "/snap"
-FULL_COMMAND_BIN = ["python", "curl", "wget", "node", "java"]
+FULL_COMMAND_BIN = ["python", "curl", "wget", "node", "java", "ssh"]
# label displayed in the pop-up combo
DURATION_session = QC.translate("popups", "until reboot")
From ab5f326e69c851fcd4d0bb4ed7ad54f741f10493 Mon Sep 17 00:00:00 2001
From: Vu Huy Nguyen <26673584+blaccod@users.noreply.github.com>
Date: Mon, 6 Apr 2026 17:19:20 +0200
Subject: [PATCH 4/5] add UI to configure the list in settings
---
ui/opensnitch/config.py | 1 +
ui/opensnitch/dialogs/preferences/settings.py | 11 +++++++++
ui/opensnitch/dialogs/prompt/utils.py | 10 +++++++-
ui/opensnitch/res/preferences.ui | 23 +++++++++++++++++++
4 files changed, 44 insertions(+), 1 deletion(-)
diff --git a/ui/opensnitch/config.py b/ui/opensnitch/config.py
index d5ae2e5c6d..4d0bd4e8b9 100644
--- a/ui/opensnitch/config.py
+++ b/ui/opensnitch/config.py
@@ -111,6 +111,7 @@ class Config:
DEFAULT_POPUP_ADVANCED_CHECKSUM = "global/default_popup_advanced_checksum"
DEFAULT_FW_INTERCEPTION_ENABLED = "global/interception_enabled"
DEFAULT_PERSIST_INTERCEPTION_STATE = "global/persist_interception_state"
+ DEFAULT_POPUP_ADVANCED_FULL_COMMAND = "global/default_popup_advanced_full_command"
DEFAULT_SERVER_ADDR = "global/server_address"
DEFAULT_SERVER_MAX_MESSAGE_LENGTH = "global/server_max_message_length"
DEFAULT_SERVER_MAX_WORKERS = "global/max_workers"
diff --git a/ui/opensnitch/dialogs/preferences/settings.py b/ui/opensnitch/dialogs/preferences/settings.py
index bd4b586128..00aff75e1c 100644
--- a/ui/opensnitch/dialogs/preferences/settings.py
+++ b/ui/opensnitch/dialogs/preferences/settings.py
@@ -9,6 +9,7 @@
from opensnitch.config import Config
from opensnitch.utils import languages
from opensnitch.database import Database
+from opensnitch.dialogs.prompt import constants as prompt_constants
from opensnitch.dialogs.preferences import (
utils,
)
@@ -59,6 +60,15 @@ def load(win):
win.uidCheck.setChecked(win.cfgMgr.getBool(win.cfgMgr.DEFAULT_POPUP_ADVANCED_UID))
win.checkSum.setChecked(win.cfgMgr.getBool(win.cfgMgr.DEFAULT_POPUP_ADVANCED_CHECKSUM))
+ default_full_cmds = ",".join(prompt_constants.FULL_COMMAND_BIN)
+ if win.cfgMgr.hasKey(win.cfgMgr.DEFAULT_POPUP_ADVANCED_FULL_COMMAND):
+ full_cmds = win.cfgMgr.getSettings(win.cfgMgr.DEFAULT_POPUP_ADVANCED_FULL_COMMAND)
+ if full_cmds is None:
+ full_cmds = ""
+ else:
+ full_cmds = default_full_cmds
+ win.fullCommandBin.setText(str(full_cmds))
+
## rules
win.comboUIRules.blockSignals(True)
win.comboUIRules.setCurrentIndex(win.cfgMgr.getInt(win.cfgMgr.DEFAULT_IGNORE_TEMPORARY_RULES))
@@ -211,6 +221,7 @@ def save_ui_config(win):
win.cfgMgr.setSettings(win.cfgMgr.DEFAULT_POPUP_ADVANCED_DSTPORT, bool(win.dstPortCheck.isChecked()))
win.cfgMgr.setSettings(win.cfgMgr.DEFAULT_POPUP_ADVANCED_UID, bool(win.uidCheck.isChecked()))
win.cfgMgr.setSettings(win.cfgMgr.DEFAULT_POPUP_ADVANCED_CHECKSUM, bool(win.checkSum.isChecked()))
+ win.cfgMgr.setSettings(win.cfgMgr.DEFAULT_POPUP_ADVANCED_FULL_COMMAND, win.fullCommandBin.text())
win.cfgMgr.setSettings(win.cfgMgr.NOTIFICATIONS_ENABLED, bool(win.groupNotifs.isChecked()))
win.cfgMgr.setSettings(win.cfgMgr.NOTIFICATIONS_TYPE,
diff --git a/ui/opensnitch/dialogs/prompt/utils.py b/ui/opensnitch/dialogs/prompt/utils.py
index 4f118446df..791dd60283 100644
--- a/ui/opensnitch/dialogs/prompt/utils.py
+++ b/ui/opensnitch/dialogs/prompt/utils.py
@@ -228,6 +228,14 @@ def set_default_duration(cfg, durationCombo):
else:
durationCombo.setCurrentIndex(Config.DEFAULT_DURATION_IDX)
+def _get_full_command_bins(cfg):
+ if cfg.hasKey(cfg.DEFAULT_POPUP_ADVANCED_FULL_COMMAND):
+ full_cmds = cfg.getSettings(cfg.DEFAULT_POPUP_ADVANCED_FULL_COMMAND)
+ if full_cmds is not None:
+ return [x.strip() for x in full_cmds.split(",") if x.strip()]
+ return []
+ return constants.FULL_COMMAND_BIN
+
def set_default_target(combo, con, cfg, app_name, app_args):
# set appimage as default target if the process path starts with
# /tmp/._mount
@@ -244,7 +252,7 @@ def set_default_target(combo, con, cfg, app_name, app_args):
return
# entire command as default target for "dangerous" commands
# (e.g. curl, wget, node)
- elif any(connection_path.name.startswith(bin) for bin in constants.FULL_COMMAND_BIN):
+ elif any(connection_path.name.startswith(bin) for bin in _get_full_command_bins(cfg)):
combo.setCurrentIndex(1)
return
diff --git a/ui/opensnitch/res/preferences.ui b/ui/opensnitch/res/preferences.ui
index 8b05b413c6..a4b6d88c25 100644
--- a/ui/opensnitch/res/preferences.ui
+++ b/ui/opensnitch/res/preferences.ui
@@ -546,6 +546,29 @@
+ -
+
+
+
+ 0
+ 0
+
+
+
+ Full command by default
+
+
+ Comma-separated list of commands that will be selected by default in the pop-up dialog.
+
+
+
+ -
+
+
+ e.g. python, curl (leave empty to disable)
+
+
+
From 0866052c81372763727981d5a219866f20979654 Mon Sep 17 00:00:00 2001
From: Vu Huy Nguyen <26673584+blaccod@users.noreply.github.com>
Date: Mon, 6 Apr 2026 17:28:18 +0200
Subject: [PATCH 5/5] Update UI writing to be more clear
---
ui/opensnitch/res/preferences.ui | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/ui/opensnitch/res/preferences.ui b/ui/opensnitch/res/preferences.ui
index a4b6d88c25..fb0154b494 100644
--- a/ui/opensnitch/res/preferences.ui
+++ b/ui/opensnitch/res/preferences.ui
@@ -555,17 +555,17 @@
- Full command by default
+ Filter by full command by default
- Comma-separated list of commands that will be selected by default in the pop-up dialog.
+ List of commands that will be selected to filter as "from this command line" by default in the pop-up dialog.
The list should be comma-separated without spaces.
It would match all commands that starts with a word in the list.
-
- e.g. python, curl (leave empty to disable)
+ e.g. python,curl (leave empty to disable)