security(P0): close unauthenticated RCE chain
The local FastAPI server previously exposed macro create/execute over the
network with no authentication while bound to 0.0.0.0, and macro `app`
commands ran via subprocess with shell=True — an unauthenticated RCE for
anyone on the LAN (and, via the relay, the internet).
- Mandatory per-install auth token (secrets.token_urlsafe) required on all
/api/* routes and the /ws handshake; timing-safe hmac.compare_digest.
PWA shell + /static assets remain public to bootstrap.
- Token auto-generated and persisted in settings.json (now chmod 0600).
- Bind host is configurable (web.allow_lan); token is the security boundary.
- macro `app` launch no longer uses shell=True — commands are tokenized with
shlex and exec'd directly, killing ;/&&/|/$() shell chaining.
- Relay client injects the local token and only forwards /api/* paths, and no
longer forwards attacker-supplied headers to the local server.
- Fixed path traversal in /api/image/{path} (realpath-confined to macro_images).
- GUI embeds the token in the LAN URL/QR; PWA reads it and sends it on API,
WebSocket, and image requests.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+11
-2
@@ -3,6 +3,7 @@
|
||||
import copy
|
||||
import json
|
||||
import os
|
||||
import shlex
|
||||
import uuid
|
||||
import pyautogui
|
||||
import subprocess
|
||||
@@ -316,10 +317,18 @@ class MacroManager:
|
||||
time.sleep(ms / 1000.0)
|
||||
|
||||
elif cmd_type == "app":
|
||||
# Launch application
|
||||
# Launch application.
|
||||
# SECURITY: shell=True was removed to kill shell-metacharacter
|
||||
# injection (no ; && | $() chaining). We tokenize the command
|
||||
# and exec the program directly without a shell.
|
||||
command = cmd.get("command", "")
|
||||
if command:
|
||||
subprocess.Popen(command, shell=True)
|
||||
try:
|
||||
args = shlex.split(command, posix=(os.name != "nt"))
|
||||
if args:
|
||||
subprocess.Popen(args)
|
||||
except Exception as e:
|
||||
print(f"Error launching app command: {e}")
|
||||
|
||||
# Legacy API compatibility methods
|
||||
def add_macro_legacy(
|
||||
|
||||
Reference in New Issue
Block a user