威胁模型(v0)
September 2, 2026 · View on GitHub
与
01-mvp-scope.md配套。技术名词保留英文。
文档示例一律使用example.com/127.0.0.1/YOUR_TOKEN占位,不得写入真实 token、私钥或内网主机名。
资产
| 资产 | 说明 |
|---|---|
deviceToken | 配对后手机持有的长期秘密。服务端只存 SHA-256 哈希。 |
| 服务端 X25519 私钥 | 数据面 E2EE 的身份锚。文件 0600,目录 0700。 |
| 会话内容 | Agent 输出、用户短回复、当前会话元数据。经 E2EE 后对中继/旁路不可读。 |
| 审批决策 | 批准 / 拒绝 / 提问应答。写操作必须可归因到 deviceId。 |
攻击者
| 攻击者 | 能力假设 |
|---|---|
| LAN 被动嗅探 | 可读同网段明文 HTTP / WS。 |
| LAN 主动 MITM | 可 ARP/DNS 欺骗,在页面加载时注入或替换 JS。 |
| QR 泄露 | 拍照、截图、投屏使 pairing offer 离开操作者控制。 |
| 手机丢失 | 已配对设备落入他人之手,直到吊销。 |
| 恶意插件 | 与本插件同住一个 DSH profile,可读部分宿主服务。 |
| 自建中继运营者 | 控制 Worker 源码与 Cloudflare 账号;可见连接元数据;PIN 路径可见 offer。 |
安全不变量
- 未认证连接只处理握手。 数据面在完成配对握手之前,不接受任何业务 RPC、不返回会话内容。
- 秘密落地约束。
deviceToken只存 SHA-256 哈希;私钥、注册表、审计文件权限 0600(所在目录 0700);密钥永不进入日志、截图或仓库。 - RPC 白名单默认拒绝。 未知方法一律拒绝。写操作(审批、提问应答、短回复)写入审计记录,可归因到
deviceId。 - 管理面 owner 围栏。 管理面始终只绑回环。本机/SSH 必须是 loopback TCP peer 与匹配的 loopback Host/Origin;HTTPS 反代还必须同时满足精确 peer allowlist、精确 HTTPS Origin/Host、代理鉴权后注入的 owner proof、
Sec-Fetch-Site: same-origin与独立 mutation CSRF proof。非受信 peer 的X-Forwarded-*一律忽略,配置不完整 fail closed。 - 不触碰宿主围栏。 不修改、不削弱
dsh web/api的绑定与鉴权;不抢api-proxy的审批 / 提问 provider。 - 文档占位。 一切公开示例使用
example.com/127.0.0.1/YOUR_TOKEN,不出现真实地址或凭据。
诚实边界(v0)
手机页经 LAN HTTP 明文下发。主动 LAN MITM 可在页面加载时注入恶意 JS;页面一旦被替换,后续 E2EE 只保护「恶意脚本与服务器之间」的信道,管不到投递层。
这是浏览器客户端相对签名原生 App 的固有差距,不是本里程碑的实现疏漏。/m 响应附带 CSP(script-src 'self'、frame-ancestors 'none')与 X-Frame-Options: DENY,用来收窄已合法下发页面被注入后的能力;它不能阻止首次 HTTP 被替换。
缓解(按优先级):
- 推荐把数据面放在 Tailscale / WireGuard 等加密 overlay 内,而不是裸 LAN。
- Cloudflare Quick Tunnel(方案 1,本里程碑),设置页显式开启,只暴露数据面:
/m会公开可达:任何人持有https://<随机>.trycloudflare.com即可加载手机页。TLS 在 Cloudflare 边缘终结,回源http://127.0.0.1:6879。- 配对仍是 fragment + E2EE:
/m静态页面本身不含会话秘密;没有 fragment 令牌(+ 共享密钥)仍不能完成e2ee_auth。URL 等同临时钥匙,勿转发。 - 必须随 unload /「停止」杀掉
cloudflared子进程(ctx.effectdisposer)。 - 禁止把
3080/dsh web送进隧道;隧道--url只指向127.0.0.1:<数据面端口>。
- M4 可选:自签 HTTPS + 二维码钉死证书哈希(TOFU)。
- 未来选项:路线 C 原生 App,用签名包投递客户端,彻底离开「首次 HTTP 下发」模型。
- 方案 2:自建会合中继(M5),设置页显式开启,桌面与手机各自出站连操作者自己的 Worker:
- 不把本机
6879/3080打到公网;中继只做会合与密文转发。 - 投递层是边缘 TLS:裸 LAN MITM 换不了
/m。被攻破的 Worker 仍可下发恶意 JS——自建 = 信任该 CF 账号与该源码。 - QR fragment 不到 Worker;PIN 兑换(
POST /m/claim)会让 Worker 运营者在 TTL 内看见完整 offer(含deviceToken)。 - Worker 可见连接元数据(谁在连、帧长/时间),不可见
e2ee_auth之后的 RPC 明文。 - 禁止把
3080/dsh web接到 Worker;禁止本仓库运营公共会合点。 - 规格见
05-cloud-relay.md。
- 不把本机
明确出界(v0 不防、不声称防):
- 桌面被控(攻击者已在跑
dsh web的机器上) - 浏览器扩展窃取设置页 / 配对码
- 通用 XSS(宿主或其它插件的 DOM 注入)
- 手机页把 X25519 私钥与 resume offer 放在
sessionStorage(非localStorage):关标签即失效,降低共享设备上的残留;仍无法抵御同页 XSS 读存储
禁止事项 / Prohibitions
以下文案可直接展示给用户(中英对照)。
- 不共享他人凭据。 Do not share another person's credentials.
- 不监测未授权账户。 Do not monitor accounts you are not authorized to access.
- 不裸暴露公网端口。 Do not bind the data-plane port on
0.0.0.0to the public Internet. A user-started Cloudflare Quick Tunnel (HTTPS at the edge, localhost origin) or a self-hosted rendezvous Worker (desktop outbound only) is an explicit exception; never tunnel3080. - 不暗示 DeepSeek 官方背书。 This plugin is not affiliated with, and is not endorsed by, DeepSeek.
错误示例(禁止照抄到生产):ws://203.0.113.10:6879?token=s3cret
正确示例:ws://127.0.0.1:6879 或 wss://example.com,token 写作 YOUR_TOKEN。