文件历史

提交图

2 次代码提交

作者 SHA1 备注 提交日期
Saurav Panda ad39a9500a harden ping/identify against non-positive pids and non-dict payloads
Two additional codex findings on 6d412c9:

1. _ipc.identify() accepted any int as pid, including 0 and negatives.
   On POSIX, os.kill(0, sig) signals every process in the calling
   process group, and os.kill(-1, sig) signals every process the
   caller can. A hostile or buggy daemon replying {pid: 0} or
   {pid: -1} would have turned restart_daemon() into a process-group
   kill. Restrict to pid > 0.

2. _ipc.ping() still did resp.get('pong') without a type check, so a
   list/scalar/null reply would raise AttributeError. The previous
   commit added that guard to identify() but left ping() bare. With
   the new daemon_alive fallback in restart_daemon() that now calls
   ping(), an unhandled raise here would abort restart before
   cleanup ran. Mirrored the identify() guards: isinstance(resp, dict)
   plus AttributeError in the except.

Tests in tests/unit/test_ipc.py now also cover:
- identify() rejects pid=0, pid=-1, pid=-42, pid=-99999
- ping() returns False for non-dict payloads (list/str/int/None)
- ping() requires pong is exactly True (rejects truthy non-True values)

Full suite: 71 passed.
2026-05-04 17:34:44 -07:00
Saurav Panda 6d412c9ee2 identify(): reject bool pid and non-dict ping payloads
Two related cubic/codex findings on _ipc.identify():

1. isinstance(pid, int) accepts bool (since bool subclasses int in
   Python), so a hostile or buggy daemon replying {pid: True} would
   yield PID 1 and os.kill(1, SIGTERM) would target init on POSIX.
   Switched to type(pid) is int — strict same-type check, no subclass
   surprises.

2. request() returns whatever JSON the daemon sent, which can be a
   list, scalar, or None for a stale/hostile endpoint. resp.get(...)
   would then raise AttributeError, propagating out of identify() and
   crashing restart_daemon() before its cleanup runs. Added an
   isinstance(resp, dict) guard and AttributeError to the except.

Tests in new tests/unit/test_ipc.py cover both rejections plus the
happy path, the missing-pid path (pre-upgrade daemon), pong=False,
and several non-dict shapes (list, str, int, None). Full suite: 67
passed.
2026-05-04 17:14:18 -07:00