# workbuddy 评审反馈 — 2026-06-14 P0 安全止血 **推送内容**: WS token 鉴权改造 + 坐席本地密码 + secret 管理规划文档 **评审日期**: 2026-06-14 **评审人**: Claude **主报告**: `D:\资料\03-项目开发\wecom_it_smart_desk\docs\评审报告\workbuddy-2026-06-14-P0安全.md` **commit**: 3735dc0 (本地 main,未推 Gitea) --- ## ⭐ 给 workbuddy 的关键反馈(高优先级) 1. **🔴 浏览器 WebSocket API 不支持自定义 header** — 误用 Node.js `ws` 库的 options.headers 2. **🔴 nginx access_log 没关** — 即使前端修好,token 仍经 access_log 泄露 3. **🟡 Mapped[str] + nullable=True 类型不一致** — 改 Optional[str] 4. **🟡 企微降级放行仍能绕过 password 验证** — P0-#5 被反削弱 5. **🟡 requirements.txt 缺 passlib** — 部署会 ImportError ## 🔴 遗留 5 项(下一轮必修) | # | 严重度 | 文件 | 修复要点 | |---|---|---|---| | 1 | 🔴 P0 | `frontend-agent/.../useWebSocket.ts:106-110` | 改 `new WebSocket(wsUrl, [\`bearer.${token}\`])` + 服务端从 `sec-websocket-protocol` 取 | | 2 | 🔴 P0 | `nginx.conf` + `deploy-server/nginx.conf` | 加 `location /ws/ { access_log off; }` | | 3 | 🟡 P1 | `backend/app/models/agent.py:142-148` | `Mapped[str]` → `Mapped[Optional[str]]` | | 4 | 🟡 P1 | `backend/app/api/agents.py` 降级放行 | 检测 `agent.password_hash` 存在 → 强制 password | | 5 | 🟡 P1 | `backend/requirements.txt` | 加 `passlib[bcrypt]==1.7.4` 或改用原生 `bcrypt==4.1.2` | ## 🟢 评审验收 - ✅ ws.py 服务端:header 优先 + query 降级,**逻辑正确** - ✅ model 字段定义:`password_hash` String(128) nullable,**结构 OK**(类型注解除外) - ✅ schema:`AgentLogin.password` + `AgentPasswordUpdate`,**OK** - ✅ 改密端点 `POST /agents/password`:走 `Depends(get_current_agent)`,**OK** - ✅ alembic 008:down_revision='007_role_system' 正确,**OK** - ✅ docs/安全/secret-管理.md:**作为规划文档 OK** ## 📊 完成度 | 任务 | 完成 | |---|---| | P0-#1 WECOM_SECRET 集中化 | 🟡 仅规划文档 | | P0-#2 SSL 私钥在仓 | 🟢 之前已修(8-A 阶段) | | P0-#3 Mock login | 🟢 之前已修 | | P0-#4 WS token URL/日志 | 🟡 半成品(服务端 OK,前端 + nginx 待关) | | P0-#5 坐席本地密码 | 🟡 半成品(模型/Schema/端点 OK,类型 + 降级 + 依赖) | **整体**: 2/5 P0 真正完成,3 项遗留待下一轮。 ## 🔁 流程建议 - 推送前自检清单: - [ ] 浏览器 WebSocket API 边界(不要用 `ws` 库的 options.headers) - [ ] nginx/conf 改动 plan 写了就必须做 - [ ] Mapped[T] + nullable=True 必须用 Optional - [ ] 改代码必须同步 requirements.txt - [ ] 加新鉴权必须 review 已有降级路径是否被绕过 - **强烈建议**: workbuddy 推送前先回答"我的改动在浏览器侧能跑吗?"(不要假设 Node.js API = 浏览器 API) ## 🔗 推 Gitea 状态 - **本地 commit 3735dc0**: ✅ 已存 - **推 Gitea**: 🔴 卡 #8(MariaDB 套件未装) - **下次**: Gitea 起来后 `git push -u origin main` 推 → workbuddy 拿 Gitea URL 二次评审