Description
Two instances of command injection via subprocess.run(..., shell=True) in tui_gateway/server.py.
Instance 1: Quick commands (line 2308)
qcmds = _load_cfg().get("quick_commands", {})
if name in qcmds:
qc = qcmds[name]
if qc.get("type") == "exec":
r = subprocess.run(qc.get("command", ""), shell=True, capture_output=True, text=True, timeout=30)
The command value comes from user config (_load_cfg()) with zero sanitization.
Instance 2: HTTP command execution (line 3131)
r = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=30, cwd=os.getcwd())
User-supplied command from HTTP request params is passed directly to a shell. The safety check (detect_dangerous_command) is wrapped in except ImportError: pass, so if the import fails, all commands run unfiltered.
Impact
Severity: Critical — Direct shell command injection.
Suggested Fix
- Replace
shell=True with subprocess.run(shlex.split(cmd), shell=False, ...)
- For quick commands, validate/sanitize before execution
- Change
except ImportError: pass to block execution when the safety module is unavailable
🤖 Generated with Claude Code
Description
Two instances of command injection via
subprocess.run(..., shell=True)intui_gateway/server.py.Instance 1: Quick commands (line 2308)
The
commandvalue comes from user config (_load_cfg()) with zero sanitization.Instance 2: HTTP command execution (line 3131)
User-supplied command from HTTP request params is passed directly to a shell. The safety check (
detect_dangerous_command) is wrapped inexcept ImportError: pass, so if the import fails, all commands run unfiltered.Impact
Severity: Critical — Direct shell command injection.
Suggested Fix
shell=Truewithsubprocess.run(shlex.split(cmd), shell=False, ...)except ImportError: passto block execution when the safety module is unavailable🤖 Generated with Claude Code