# 代码 Review 记录(2026-08-20,推送 git.awaioi.com 前) > 范围:server/(Go)、client/core/(Go)、apps/web(React)、client/ui+desktop(WinUI3/Electron,静态)。 > 结论:基线全绿(go build/vet/test -race、tsc --noEmit、pnpm build、desktop JS 语法)。本次修复 7 处,均在提交前落地。 ## 验证基线(全绿) - server:`go build ./...` ✓ · `go vet ./...` ✓ · `go test -race ./...` ✓(api/auth/task/ws) - client/core:`go build/vet/test -race ./...` ✓(device/exec/bilibili/cdp/localserver/vault/wsclient) - apps/web:`tsc --noEmit` ✓(0 错误)· `pnpm build` ✓(仅 >500KiB chunk 告警,非错误) - client/desktop:`node --check` 3 文件语法 ✓ ## 已修复(本次) | 级别 | 位置 | 问题 | 修复 | |---|---|---|---| | HIGH | server/internal/ws/hub.go | `send on closed channel` panic:连接注销时 `close(send)` 与 `SendToAgent`/广播并发竞态 | Conn 增加 mu+closed 标记,统一经 `sendRaw` 发送并在关闭前检查;加回归测试(含 -race) | | MED | server/internal/ws/dispatcher.go | 轮询 WHERE 缺括号:`status=? AND schedule_at is null OR schedule_at<=?` 优先级错误 | 显式括号 `(schedule_at is null or schedule_at <= ?)` | | MED | server/internal/api/handlers/agent.go | 配对码非原子占用:并发可配出多台设备 | 事务内 `UPDATE ... WHERE used=false` 并以 RowsAffected==1 判定占用 | | MED | server/internal/api/handlers/material.go | 上传无体积上限(磁盘 DoS) | http.MaxBytesReader + 配置 MAX_UPLOAD_BYTES(默认 2GiB) | | MED | server/internal/ws/hub.go | RegisterAgent 在 hub 锁内做网络 Close | 关闭动作移出锁外;旧连接 ws 关闭加 nil 保护 | | CRIT | server/internal/config/config.go | JWT_SECRET 默认值可被伪造令牌(admin 提权) | 默认/过短密钥时打印醒目安全告警 | | LOW | client/core/internal/localserver/localserver.go | token 比较非常数时间 + 支持 URL query 传递 | 仅接受请求头 + subtle.ConstantTimeCompare | ## 审查确认无问题的关键点 - 认证:Argon2id(OWASP 基线参数)+ 常数时间比较;JWT HS256 + 签名方法校验(拒绝 alg 混淆)+ refresh 轮换(Redis jti 吊销)。 - 密码/保险库:client/core vault 用 AES-256-GCM,随机 nonce、GCM 认证、master.key/vault.enc 0600、目录 0700。 - 设备握手:Ed25519 hello 验签、坏签名/未知设备/已吊销设备均拒绝。 - 素材直链:签名 token 一次性 + 10min 过期 + path 前缀校验(storageKey 服务端生成)。 - 前端:无 dangerouslySetInnerHTML / innerHTML(无 XSS 注入点);401 刷新单飞;WS 重连;登出清理令牌。 - 任务状态机:转移表完整(草稿→审核→排队→下发→执行→成功/失败→重试/取消/挂起)。 ## 遗留(低优先级,未阻塞) - 前端 JWT 存 localStorage(当下无 XSS 向量可接受;二期可改 httpOnly Cookie)。 - WSS `InsecureSkipVerify: true`(内网部署 + token 鉴权下可接受;公网需收紧 Origin 校验)。 - buildPush 每次下发失败会遗留未清理的 TransferToken(10min 过期自愈)。 - 素材 Delete 先删文件再删库,DB 失败会留悬空行(极小概率)。 - 前端 bundle 单 chunk >500KiB(可 code-split 优化)。