T09 · Insecure Skill Coding Practices
Error
- Location
- templates/modes_switch.py:387
- Finding
- Port-Only Service Identification Can Terminate Unrelated Processes<![CDATA[ ## Vulnerability Details **File Location**: `templates/modes_switch.py:387-416` **Vulnerability Type**: Unverified process ownership before termination **Risk Level**: High ### Vulnerable Code ```python def ensure_service(cfg, base, svc, want, dry=False, log=print): name, port = svc.get("name"), int(svc.get("port")) if want: if port_alive(port): log(f"service {name}:{port} running") return start_argv = svc.get("start_argv") if not start_argv: log(f"service {name}:{port} down, no start_argv (monitor only)") return if dry: log(f"service {name}:{port} WOULD start {start_argv}") return _spawn(start_argv, log=log, what=f"service {name}") deadline = time.time() + SERVICE_WAIT_S while time.time() < deadline and not port_alive(port): time.sleep(0.5) log(f"service {name}:{port} {'up' if port_alive(port) else 'did NOT come up'}") else: if not port_alive(port): log(f"service {name}:{port} already offline") return pids = _listen_pids(port) if dry: log(f"service {name}:{port} WOULD stop pid(s) {pids}") return if not pids: log(f"service {name}:{port} up but no owner pid found - left alone") return ok = all(stop_pid(p) for p in pids) log(f"service {name}:{port} {'stopped' if ok else 'stop FAILED'}") ``` ### Technical Analysis The switcher assumes that every process listening on a configured TCP port is the configured service. Although `_listen_pids()` performs an exact port comparison and therefore avoids substring errors such as confusing port `3001` with `30010`, the port number does not prove process ownership. The code does not verify any of the following before calling `stop_pid()`: - Whether the process was launched by this Skill. - Whether its executable path matches the configur ...[truncated 1718 chars]
- Remediation
- <![CDATA[ ## Remediation Suggestions - Record a service ownership file when `_spawn()` starts a service. It should contain the PID, process creation time, normalized executable path, expected command line, and a cryptographically random instance token. - Before termination, require the live process to match the recorded PID and creation time. Where supported, also compare executable path and command line. - Treat a port as a health signal only, not as authorization to terminate its owner. - If no trusted ownership record exists, leave the listener running and report that ownership could not be established. - Store ownership records in a directory writable only by the account running the switcher. - Avoid running the switcher as an administrator unless management of privileged services is explicitly required. - Add a regression test in which an unrelated process occupies a configured port and verify that mode switching refuses to terminate it. ]]>
