T09 · Insecure Skill Coding Practices
- Location
- scripts/ws_client.py:317
- Finding
- Interactive Mode Bypasses Approval Controls for Sensitive Terminal Operations<![CDATA[ ## Vulnerability Details **File Location**: `scripts/ws_client.py:317-368` **Vulnerability Type**: Missing authorization enforcement in an alternate request path **Risk Level**: High ### Vulnerable Code ```python async def cmd_interactive(client_type="ws-client", client_id=None): """Interactive mode.""" session_id = _get_session_id() ws, token = await _connect_and_identify(session_id, client_type, client_id) try: print("Connected. Type JSON requests or use shortcuts:", file=sys.stderr) print(" lw = list_workspaces | lp = list_panels | lc = list_connections", file=sys.stderr) print(" q = quit", file=sys.stderr) shortcuts = { "lw": ("list_workspaces", {}), "lp": ("list_panels", {}), "lc": ("list_connections", {}), } async def reader(): try: while True: raw = await ws.recv() data = json.loads(raw) if "event" in data: print(f"\n[EVENT] {json.dumps(data, ensure_ascii=False)}") else: print(f"\n[RESP] {json.dumps(data, ensure_ascii=False, indent=2)}") print("> ", end="", flush=True) except websockets.exceptions.ConnectionClosed: pass reader_task = asyncio.create_task(reader()) loop = asyncio.get_event_loop() try: while True: print("> ", end="", flush=True) line = await loop.run_in_executor(None, sys.stdin.readline) line = line.strip() if not line: continue if line == "q": break if line in shortcuts: method, params = shortcuts[line] req_id = str(uuid.uuid4())[:8] msg = {"id": req_id, "method": method, "params": params, "toke ...[truncated 3630 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions 1. Parse every interactive request into a validated method and parameter structure before transmission. 2. Apply `_check_approval(method, params)` to all interactive requests, particularly `send_input` and `subscribe_output`. 3. Define an explicit allowlist of methods that interactive mode may invoke. Reject unknown or undocumented methods by default. 4. Prevent callers from supplying or replacing authentication tokens. Remove any user-provided `token` field and inject the authenticated connection token internally. 5. Validate that `method` is a string and `params` is an object before evaluating authorization. 6. Centralize request authorization in a single function used by `cmd_execute()`, `cmd_subscribe()`, and `cmd_interactive()` so alternate request paths cannot bypass the control. 7. Add regression tests proving that interactive `send_input` and `subscribe_output` requests are rejected unless explicitly approved. 8. Consider removing arbitrary raw JSON support if it is not essential. A fixed set of interactive commands provides a smaller and more auditable attack surface. ]]>
