From 9d204abfae4cfa3970b2a281eb676c995f5ade06 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Mon, 23 Mar 2026 17:57:27 +0000 Subject: [PATCH 1/2] daemon: set restrictive permission on RPC-server unix domain socket 0600 instead of 0775. --- electrum/daemon.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/electrum/daemon.py b/electrum/daemon.py index a8fc2ceb1..12c7fbdea 100644 --- a/electrum/daemon.py +++ b/electrum/daemon.py @@ -34,6 +34,7 @@ from typing import Dict, Optional, Tuple, Callable, Union, Sequence, Mapping, TY from base64 import b64decode, b64encode import json import socket +import stat import aiohttp from aiohttp import web, client_exceptions @@ -43,7 +44,7 @@ from . import util from .network import Network from .util import ( json_decode, to_bytes, to_string, profiler, standardize_path, constant_time_compare, InvalidPassword, - log_exceptions, randrange, OldTaskGroup, UserFacingException, JsonRPCError + log_exceptions, randrange, OldTaskGroup, UserFacingException, JsonRPCError, os_chmod ) from .wallet import Wallet, Abstract_Wallet from .storage import WalletStorage @@ -327,6 +328,12 @@ class CommandsServer(AuthenticatedServer): await site.start() except Exception as e: raise Exception(f"failed to start CommandsServer at {self._socket_config_str()}. got exc: {e!r}") from None + # now server has started. + if self.socktype == 'unix': + # set restrictive permissions on unix domain socket. + # FIXME race? we are late. should set this during socket-file creation but aiohttp API does not let us. + os_chmod(self.sockpath, stat.S_IREAD | stat.S_IWRITE) + # write server conn details into lockfile fd if self.socktype == 'unix': addr = self.sockpath elif self.socktype == 'tcp': From 7755d97a76b705faf2f0598aa9d51c322c04806f Mon Sep 17 00:00:00 2001 From: SomberNight Date: Wed, 25 Mar 2026 16:08:53 +0000 Subject: [PATCH 2/2] set restrictive unix umask application-wide by default - I noticed we were creating the RPC server unix domain socket with 0o775. Instead of hunting down each individual line we create files/dirs, we should just set a restrictive umask by default. We can still use chmod to relax this for individual files. -- but we should try to be secure by default - note: bitcoin core does the same https://github.com/bitcoin/bitcoin/blame/2fe76ed8324af44c985b96455a05c3e8bec0a03e/src/common/system.cpp#L92 - the umask is set in run_electrum as opposed to __init__.py so that we don't side-effect use-cases where electrum is imported as a library --- run_electrum | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/run_electrum b/run_electrum index df45836e1..e0fd8457f 100755 --- a/run_electrum +++ b/run_electrum @@ -107,6 +107,15 @@ if is_android: ctypes.pythonapi = ctypes.PyDLL("libpython%d.%d.so" % sys.version_info[:2]) # replaces ctypes.PyDLL(None) +# Set default application-wide file umask to more restrictive than typical. +# We want to create all files and directories (esp. inside the datadir) with locked-down permissions. +# note: this helps even on Windows! (see https://docs.python.org/3/library/os.html#os.mkdir) +# > `os.mkdir(path, mode=0o777, *, dir_fd=None)` +# > On Windows, a mode of 0o700 is specifically handled to apply access control to the new +# > directory such that only the current user and administrators have access. +os.umask(0o0077) + + sys._ELECTRUM_RUNNING_VIA_RUNELECTRUM = True # used by logging.py from electrum.logging import get_logger, configure_logging # import logging submodule first