# -*- coding: utf-8 -*- r'''修验证智能体找到的两个低危但真实的问题。 == A. enable_relay() 第二次调用谎报成功 == if self._relay is not None: return True # <- 只要对象建过就报成功 而"没配中转地址"那条路也会把 self._relay 建起来(然后 start("") 返回 False)。 于是第二次调用拿到的是 True —— 调用方会以为中转在跑。 现在没有调用方会这样调(所以是潜伏 bug),但语义是错的。 修法:返回**真实运行状态**,而不是"对象存不存在"。 == B. 非法 deviceId(控制字符)被接受 == register() 只校验了长度: if not device_id or len(device_id) > 80: 拒绝 但 `\x00`、`\r\n` 这类控制字符能进去。 管理页的转义做得对,所以**不是 XSS**;但 deviceId 会进日志, `\r\n` 可以伪造日志行、污染 journalctl 的输出。 修法:只接受可打印的 ASCII(字母数字、-、_、.、:),其余拒绝。 真实 deviceId 是 `机器名-12位hex` 这种形状,不会用到别的字符。 ''' from __future__ import annotations import sys from pathlib import Path ROOT = Path(r"C:\Users\shu\Desktop\deepseekagent\LanRemote") def patch(path: Path, old: str, new: str, label: str) -> bool: text = path.read_text(encoding="utf-8") if old not in text: print(" ✗ 没找到:%s" % label) return False if text.count(old) != 1: print(" ! 出现 %d 次:%s" % (text.count(old), label)) return False path.write_text(text.replace(old, new, 1), encoding="utf-8", newline="\n") print(" ✓ %s" % label) return True def main() -> int: ok_all = True # ---------------------------------------------------------- A print(" ── A. enable_relay 谎报成功 ──") ok_all &= patch( ROOT / "windows" / "lanremote" / "server.py", """ if self._relay is not None: return True self._relay = RelayLink(self.store, log=self._log,""", """ # ⚠ 这里以前是 `if self._relay is not None: return True` —— # 只要对象建过就报成功。而"没配中转地址"那条路也会把对象建起来 # (start("") 返回 False),于是第二次调用会谎报中转在跑。 # 改成看**真实运行状态**。 if self._relay is not None: return bool(getattr(self._relay, "running", False)) self._relay = RelayLink(self.store, log=self._log,""", "enable_relay 返回真实状态") # ---------------------------------------------------------- B print() print(" ── B. 非法 deviceId(控制字符)──") ok_all &= patch( ROOT / "relay" / "relay.py", """ if not device_id or len(device_id) > 80: return {"ok": False, "error": "deviceId 不合法"}""", """ if not device_id or len(device_id) > 80: return {"ok": False, "error": "deviceId 不合法"} # 只接受可打印 ASCII(真实 deviceId 是「机器名-12位hex」这种形状)。 # 不放行的话 `\\x00`、`\\r\\n` 这类控制字符能进来 —— # 管理页的转义做得对所以不是 XSS,但 deviceId 会写进日志, # `\\r\\n` 可以伪造日志行、把 journalctl 的输出搅乱。 if not all(32 <= ord(ch) < 127 for ch in device_id): log(f"deviceId 含不可打印字符,拒绝:{device_id!r}") return {"ok": False, "error": "deviceId 含非法字符"}""", "register 拒绝控制字符 deviceId") print() if not ok_all: print(" 有失败项") return 1 print(" 两个都修好了") return 0 if __name__ == "__main__": sys.exit(main())