From 9cae243d1517ee4d5495509abaaadb869c3483a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sevban=20D=C3=B6nmez?= <82449360+byjanke@users.noreply.github.com> Date: Fri, 4 Sep 2026 23:05:21 +0300 Subject: [PATCH 1/2] fix: enforce secure mount options (nosuid,nodev,noexec) and restrict report permissions (CWE-266, CWE-200) --- src/util/DualBootManager.py | 26 ++++++++++++++++++-------- src/util/SystemReportManager.py | 22 ++++++++++++++++------ 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/util/DualBootManager.py b/src/util/DualBootManager.py index 6f5c9a3..cc0c85a 100644 --- a/src/util/DualBootManager.py +++ b/src/util/DualBootManager.py @@ -51,33 +51,43 @@ def get_windows_version(): def get_dualboot_oses(): dualboot = {} - os.makedirs("/run/winroot", exist_ok=True) + winroot_dir = "/run/winroot" + if os.path.islink(winroot_dir): + os.unlink(winroot_dir) + os.makedirs(winroot_dir, mode=0o700, exist_ok=True) + try: + os.chmod(winroot_dir, 0o700) + except OSError: + pass root_part = get_root_part() for part in list_parts(): if f"/dev/{part}" == root_part: continue sp = subprocess.run( - ["mount", "-o", "defaults,ro", f"/dev/{part}", "/run/winroot"], + ["mount", "-o", "ro,nosuid,nodev,noexec", f"/dev/{part}", winroot_dir], capture_output=True, ) if 0 == sp.returncode: # Windows - if os.path.exists("/run/winroot/Windows/System32/ntoskrnl.exe"): + if os.path.exists(f"{winroot_dir}/Windows/System32/ntoskrnl.exe"): dualboot[part] = "Windows " + get_windows_version() # Mac OS X if os.path.exists( - "/run/winroot/System/Library/CoreServices/SystemVersion.plist" + f"{winroot_dir}/System/Library/CoreServices/SystemVersion.plist" ): dualboot[part] = "Mac OS X" # Linux - if os.path.exists("/run/winroot/etc/os-release"): - with open("/run/winroot/etc/os-release", "r") as f: + if os.path.exists(f"{winroot_dir}/etc/os-release"): + with open(f"{winroot_dir}/etc/os-release", "r") as f: for line in f.read().split("\n"): if line.startswith("NAME="): dualboot[part] = line[6:-1] - os.system("umount -lf /run/winroot") + subprocess.run(["umount", "-lf", winroot_dir], check=False) - os.rmdir("/run/winroot") + try: + os.rmdir(winroot_dir) + except OSError: + pass return json.dumps(dualboot) diff --git a/src/util/SystemReportManager.py b/src/util/SystemReportManager.py index 265fec4..c97e985 100644 --- a/src/util/SystemReportManager.py +++ b/src/util/SystemReportManager.py @@ -64,8 +64,13 @@ def generate_report(): os.unlink(ARCHIVE_DIR) elif os.path.isdir(ARCHIVE_DIR): shutil.rmtree(ARCHIVE_DIR) - # Make dir - os.makedirs(f"{ARCHIVE_DIR}/{pkexec_user}", exist_ok=True) + # Make dir with secure 0700 permissions + os.makedirs(f"{ARCHIVE_DIR}/{pkexec_user}", mode=0o700, exist_ok=True) + try: + os.chmod(ARCHIVE_DIR, 0o700) + os.chmod(f"{ARCHIVE_DIR}/{pkexec_user}", 0o700) + except OSError: + pass # Program outputs run_and_save( @@ -125,9 +130,9 @@ def generate_report(): copy("/etc/apt/sources.list") copy("/etc/apt/sources.list.d") - # set permission and owner + # set permission and owner (0700: strictly restricted to pkexec_user) subprocess.run(["chown", pkexec_user, "-R", ARCHIVE_DIR]) - subprocess.run(["chmod", "755", "-R", ARCHIVE_DIR]) + subprocess.run(["chmod", "700", "-R", ARCHIVE_DIR]) def generate_user_report(): @@ -136,8 +141,13 @@ def generate_user_report(): ComputerManager.ComputerManager().get_all_device_info(), indent=2 ) - # Make dir - os.makedirs(f"{ARCHIVE_DIR}/{pkexec_user}", exist_ok=True) + # Make dir with secure 0700 permissions + os.makedirs(f"{ARCHIVE_DIR}/{pkexec_user}", mode=0o700, exist_ok=True) + try: + os.chmod(ARCHIVE_DIR, 0o700) + os.chmod(f"{ARCHIVE_DIR}/{pkexec_user}", 0o700) + except OSError: + pass with open(f"{ARCHIVE_DIR}/{pkexec_user}/system_info.json", "w") as f: f.write(hardware_info) From 10a980d17c04d5d402bc232aa394df45ca6df38f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sevban=20D=C3=B6nmez?= <82449360+byjanke@users.noreply.github.com> Date: Sat, 5 Sep 2026 01:49:03 +0300 Subject: [PATCH 2/2] fix: write system reports under /run instead of /tmp /tmp/pardus_system_report remains replaceable between rmtree and makedirs. /run/pardus-about-report is root-owned tmpfs, so the directory cannot be planted as a symlink by another user. --- src/util/SystemReportManager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/util/SystemReportManager.py b/src/util/SystemReportManager.py index c97e985..0364558 100644 --- a/src/util/SystemReportManager.py +++ b/src/util/SystemReportManager.py @@ -6,7 +6,7 @@ from util import ComputerManager -ARCHIVE_DIR = "/tmp/pardus_system_report" +ARCHIVE_DIR = "/run/pardus-about-report" def detect_pkexec_user(): @@ -24,7 +24,7 @@ def detect_pkexec_user(): def run_and_save(command, command_name=None): - """Usage: run_and_save(["journalctl", "-q", "-n", 1000]), it will be saved in /tmp/pardus_system_report/journalctl""" + """Usage: run_and_save(["journalctl", "-q", "-n", 1000]), it will be saved under ARCHIVE_DIR.""" if not command: return