Files
Nexus/docs/project/risk-acceptance-single-operator.md
T
Nexus Agent eab35a35be fix(security): BL-06 强制 Agent per-server key 并合并心跳单次查库
移除 Agent 认证与安装链路的 global API_KEY 回退,收口 risk-acceptance 接受项 2;巡检补修心跳重复 get_server 并加 assert_called_once 回归测试。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-07 11:17:41 +08:00

112 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 风险接受记录 — 单人运维场景(2026-06-04
## 背景
Nexus 全量 Code Review(批次 1~3)完成后,有两项被标记为「刻意未纳入」,需更大协议变更或 Agent 全站迁移:
1. WebSocket JWT 仍通过 query 传递(ADR-011
2. ~~Agent 认证保留 global `API_KEY` 对未分配 `agent_api_key` 服务器的 legacy 回退~~ **已收口(2026-06-07 BL-06**
**运营事实(2026-06-04 确认)**:后台仅 **一名** 操作员自用,无多人共享账号、无外包运维、无多租户。操作员即系统 owner,管理员身份视为完全可信。
本文档记录在该威胁模型下的**正式风险接受**与重评条件,避免后续审计或接续开发误将两项抬为 P0。
---
## 威胁模型(单人运维)
| 维度 | 假设 |
|------|------|
| 后台用户 | 仅 1 人,可信 |
| 内鬼 / 权限滥用 | 不适用 |
| 主要防护目标 | 外网未授权访问、安装/认证漏洞、多 worker 竞态、子机 Agent M2M 密钥管理 |
| 日志访问 | Nginx/宝塔等 access log 仅 operator 可阅,不外发第三方 |
---
## 接受项 1WebSocket JWT queryADR-011
### 现状
- `/ws/alerts``/ws/sync``/ws/terminal/{id}` 均在握手 URL 使用 `?token=...`
- 设计依据:ADR-011;浏览器 WebSocket 无法自定义 Authorization Header
- 批次 3 已统一:缺失 token → **4001**;无效/过期 JWT → **4401**
### 接受理由
- Token 仅在 operator 登录后由其浏览器持有,无「不可信管理员」场景
- 改首帧鉴权 / WS ticket / 子协议需前后端同发、三条通道联测,**单人自用 ROI 极低**
- 残余风险(access log 留存 JWT、DevTools 可见)在「仅 operator 可读日志」前提下可接受
### 残余风险
- 本机恶意软件可窃取 session(与 token 在 query 或 Header 无本质差别)
- 若未来日志外发 SIEM/第三方,URL 中的 JWT 成为额外泄露面
### 重评触发条件
- 新增第二管理员或外包运维
- 等保/客户安全审计要求「凭证不得出现在 URL」
- access log 外发或多人可读
- 后台改为多租户或 SaaS 形态
### 决定
**维持 ADR-011,不排 WS 协议改造。**
---
## 接受项 2Agent global API_KEY legacy 回退 — **已收口(2026-06-07**
### 原状(2026-06-04 接受)
- 子机 Agent 通过 `X-API-Key` 调用 `/api/agent/heartbeat`(无 JWT、无后台登录)
- 认证逻辑曾允许:未分配 `agent_api_key` 时回退接受 global `API_KEY`(写 warning 日志)
### 收口决定(BL-06
- **2026-06-07**:生产 0 台子机窗口,移除 global 回退,强制 per-server `agent_api_key`
- 改动点:`server/api/agent.py``server/api/servers.py`(安装链路)、`server/application/services/script_service.py`(长任务回调)
- global `API_KEY` 仍保留为必需环境变量(启动校验、加密等非 Agent 用途),**不再作为 Agent 认证通行证**
### 运维语义
- 新建服务器自动生成 `nxs-...` per-server key
- `uninstall-agent` 会将 `agent_api_key``None`;重装前须 `POST /api/servers/{id}/agent-key` 重新生成
### 残余风险
- **已消除**global key 伪造未迁移服务器心跳的面已关闭
- 接受项 2 自 2026-06-07 起**作废**,不再作为开放风险项
---
## 仍须保持的修复(与单人场景无关)
以下项已在 Code Review 批次 1~3 修复,属于**稳定性/外网暴露**问题,不因单人运维而降级:
- Sync/脚本并行任务 AsyncSession 竞态
- 安装向导 create-admin 鉴权窗口
- schedule/retry 多 worker 重复执行
- 登录开放重定向、推送 WS 断线与 logout 码
- Settings 敏感项脱敏、Agent unknown server 拒绝等
---
## 变更记录
| 日期 | 说明 |
|------|------|
| 2026-06-04 | 初始记录;operator 确认单人自用后台 |
| 2026-06-07 | 接受项 2 收口:BL-06 强制 per-server agent_api_key,移除 global 回退 |
---
## 引用
- ADR-011`docs/project/roadmap.md`WebSocket JWT query
- Code Review 批次 3`docs/changelog/2026-06-04-code-review-p1-p2-batch3.md`
- 本记录 changelog`docs/changelog/2026-06-04-risk-acceptance-single-operator.md`
- AI 接续:`docs/project/AI-HANDOFF-2026-05-23.md` §7b · `docs/project/AI-HANDOFF-2026-06-03.md` §Code Review 收尾
- Agent 认证实现:`server/api/agent.py``_verify_server_api_key`