mirror of
https://github.com/saphid/frame-control.git
synced 2026-10-06 06:00:33 +02:00
Terminal launcher and setup hardening from the second review
- lxterminal and tilix take the command as one string after -e. - Refuse quotes and % in Windows terminal commands instead of a bogus escape. - frame_connect validates FRAME_ALIAS and FRAME_USER before writing ~/.ssh/config. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
e210407f31
commit
52d01bd815
2 files changed
+20
-6
No files matched your search
+5
-1
@@ -21,6 +21,10 @@ FRAME_ALIAS = os.environ.get("FRAME_ALIAS", "frame")
|
|||||||
SSH_DIR = Path.home() / ".ssh"
|
SSH_DIR = Path.home() / ".ssh"
|
||||||
KEY = SSH_DIR / "id_ed25519_frame"
|
KEY = SSH_DIR / "id_ed25519_frame"
|
||||||
CONFIG = SSH_DIR / "config"
|
CONFIG = SSH_DIR / "config"
|
||||||
|
# Both go into ~/.ssh/config, so nothing that could add a line or a directive.
|
||||||
|
for _name, _value in (("FRAME_ALIAS", FRAME_ALIAS), ("FRAME_USER", FRAME_USER)):
|
||||||
|
if not re.fullmatch(r"[A-Za-z0-9][A-Za-z0-9._-]*", _value):
|
||||||
|
sys.exit(f"{_name} must be a plain name, not {_value!r}")
|
||||||
BEGIN = f"# >>> steam-frame ({FRAME_ALIAS}) >>>"
|
BEGIN = f"# >>> steam-frame ({FRAME_ALIAS}) >>>"
|
||||||
END = f"# <<< steam-frame ({FRAME_ALIAS}) <<<"
|
END = f"# <<< steam-frame ({FRAME_ALIAS}) <<<"
|
||||||
|
|
||||||
@@ -125,7 +129,7 @@ def main(argv):
|
|||||||
say("==> Looking for the Steam Frame")
|
say("==> Looking for the Steam Frame")
|
||||||
found = pick_host(argv[0] if argv else None)
|
found = pick_host(argv[0] if argv else None)
|
||||||
while not found:
|
while not found:
|
||||||
say("Could not reach the Frame on port 22.")
|
say("Could not reach the Frame over SSH.")
|
||||||
say("Check: Developer Mode on and a user password set; same network; no client isolation.")
|
say("Check: Developer Mode on and a user password set; same network; no client isolation.")
|
||||||
try:
|
try:
|
||||||
typed = input("Type the Frame's IP address (Quick Settings shows it), or press Enter to quit: ").strip()
|
typed = input("Type the Frame's IP address (Quick Settings shows it), or press Enter to quit: ").strip()
|
||||||
|
|||||||
+15
-5
@@ -146,19 +146,29 @@ def open_terminal(argv, title="Frame Control"):
|
|||||||
# `start` gives the command its own console window; cmd /k keeps it open.
|
# `start` gives the command its own console window; cmd /k keeps it open.
|
||||||
# One hand-built command line: quoting it twice through list2cmdline would
|
# One hand-built command line: quoting it twice through list2cmdline would
|
||||||
# produce backslash-escaped quotes, which cmd doesn't understand.
|
# produce backslash-escaped quotes, which cmd doesn't understand.
|
||||||
# Every argument is quoted, so cmd treats & | < > ^ in them literally.
|
# Every argument is quoted, so cmd treats & | < > ^ in them literally. cmd has
|
||||||
inner = " ".join('"%s"' % a.replace('"', '\\"') for a in argv)
|
# no escape for a quote inside quotes (and expands %VAR% regardless), so refuse those.
|
||||||
|
if any(c in a for a in argv for c in '"%\r\n'):
|
||||||
|
raise HostError("Can't pass quotes or % to a Windows terminal")
|
||||||
|
inner = " ".join(f'"{a}"' for a in argv)
|
||||||
subprocess.Popen(f'cmd.exe /c start "{title}" cmd.exe /k "{inner}"', **DETACHED)
|
subprocess.Popen(f'cmd.exe /c start "{title}" cmd.exe /k "{inner}"', **DETACHED)
|
||||||
return "a terminal window"
|
return "a terminal window"
|
||||||
script = f'{shlex.join(argv)}; echo; read -r -p "Press Enter to close. " _'
|
script = f'{shlex.join(argv)}; echo; read -r -p "Press Enter to close. " _'
|
||||||
|
# flags=None: the terminal takes the whole command as one string after -e.
|
||||||
for name, flags in (("x-terminal-emulator", ["-e"]), ("gnome-terminal", ["--"]), ("ptyxis", ["--"]),
|
for name, flags in (("x-terminal-emulator", ["-e"]), ("gnome-terminal", ["--"]), ("ptyxis", ["--"]),
|
||||||
("kgx", ["--"]), ("konsole", ["-e"]), ("xfce4-terminal", ["-x"]),
|
("kgx", ["--"]), ("konsole", ["-e"]), ("xfce4-terminal", ["-x"]),
|
||||||
("tilix", ["-e"]), ("lxterminal", ["-e"]), ("kitty", []), ("alacritty", ["-e"]),
|
("tilix", None), ("lxterminal", None), ("kitty", []), ("alacritty", ["-e"]),
|
||||||
("wezterm", ["start", "--"]), ("foot", []), ("xterm", ["-e"])):
|
("wezterm", ["start", "--"]), ("foot", []), ("xterm", ["-e"])):
|
||||||
exe = which(name)
|
exe = which(name)
|
||||||
if exe:
|
if not exe:
|
||||||
|
continue
|
||||||
|
if flags is None:
|
||||||
|
_spawn([exe, "-e", "bash -c " + shlex.quote(script)])
|
||||||
|
elif name == "x-terminal-emulator" and "lxterminal" in os.path.realpath(exe):
|
||||||
|
_spawn([exe, "-e", "bash -c " + shlex.quote(script)]) # Debian alternative -> lxterminal
|
||||||
|
else:
|
||||||
_spawn([exe, *flags, "bash", "-c", script])
|
_spawn([exe, *flags, "bash", "-c", script])
|
||||||
return name
|
return name
|
||||||
raise HostError("No terminal program found (tried gnome-terminal, konsole, xterm and others)")
|
raise HostError("No terminal program found (tried gnome-terminal, konsole, xterm and others)")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user