Hi - while reading the code I noticed a few hardening opportunities. Grouping them here for discussion before sending any PR, since some touch areas where you may have a reason for the current approach (especially the TLS one). Happy to open focused PRs for whichever you'd accept.
1. subprocess(..., shell=True) - lib/process_manager.py
def run(args: list[str], cwd=None):
return subprocess.Popen(args, cwd=cwd, shell=True, ...) # L32
def run_ps(args: str):
return subprocess.call(text, shell=True) # L39
run() already receives a list; on Windows shell=True with a list is ambiguous and unnecessary. All callers in launch.py pass a real executable + args, so shell=False would be more predictable and drop the shell-parsing surface. (Note: test/test_process.py uses ["echo", "test"], where echo is a shell builtin - that test would need a real exe.)
2. PowerShell command injection - run_ps()
args = args.replace('"', '\\"').replace("\n", "").replace("\r", "")
text = f'powershell -Command "{args}"'
The shortcut template is interpolated into -Command with only quote/newline escaping. A safer pattern is to write the script to a temp .ps1 and invoke powershell -ExecutionPolicy Bypass -File <path>, which removes the string-interpolation surface entirely.
3. TLS verification disabled - lib/DGPSessionV2.py, tab/account.py
urllib3.disable_warnings() # DGPSessionV2 L19
... post_device_dgp(url, json=json, verify=False) # L203
... verify=False ... # account.py L291/314/362/379
verify=False on the DMM device endpoints disables certificate validation (MITM exposure). Is this required by a specific DMM endpoint's certificate, or is it incidental? If incidental, enabling verification (and dropping disable_warnings()) would close the hole. If a particular host needs it, scoping verify=False to just that request would be safer than the session-wide default.
4. Scheduled-task XML built by string replace - Schtasks.set()
template = template.replace(r"{{ARGUMENTS}}", " ".join(...))
template = template.replace(r"{{WORKING_DIRECTORY}}", os.getcwd())
User-derived values (username via the UID, cwd, args) are interpolated into the task XML unescaped. A path or arg containing &, <, > produces malformed XML. xml.sax.saxutils.escape() on each substituted value fixes it.
5. Minor: dead code
ProcessManager.search_process() has no caller in the tree.
None of these are urgent; #3 and #4 are the most worth a look. Let me know which you'd like as PRs and I'll keep them small and focused.
Hi - while reading the code I noticed a few hardening opportunities. Grouping them here for discussion before sending any PR, since some touch areas where you may have a reason for the current approach (especially the TLS one). Happy to open focused PRs for whichever you'd accept.
1.
subprocess(..., shell=True)-lib/process_manager.pyrun()already receives a list; on Windowsshell=Truewith a list is ambiguous and unnecessary. All callers inlaunch.pypass a real executable + args, soshell=Falsewould be more predictable and drop the shell-parsing surface. (Note:test/test_process.pyuses["echo", "test"], whereechois a shell builtin - that test would need a real exe.)2. PowerShell command injection -
run_ps()The shortcut template is interpolated into
-Commandwith only quote/newline escaping. A safer pattern is to write the script to a temp.ps1and invokepowershell -ExecutionPolicy Bypass -File <path>, which removes the string-interpolation surface entirely.3. TLS verification disabled -
lib/DGPSessionV2.py,tab/account.pyverify=Falseon the DMM device endpoints disables certificate validation (MITM exposure). Is this required by a specific DMM endpoint's certificate, or is it incidental? If incidental, enabling verification (and droppingdisable_warnings()) would close the hole. If a particular host needs it, scopingverify=Falseto just that request would be safer than the session-wide default.4. Scheduled-task XML built by string replace -
Schtasks.set()User-derived values (username via the UID, cwd, args) are interpolated into the task XML unescaped. A path or arg containing
&,<,>produces malformed XML.xml.sax.saxutils.escape()on each substituted value fixes it.5. Minor: dead code
ProcessManager.search_process()has no caller in the tree.None of these are urgent; #3 and #4 are the most worth a look. Let me know which you'd like as PRs and I'll keep them small and focused.