# API 巡检 B1 — servers.py + webssh.py

**日期**: 2026-06-06  
**范围**: `server/api/servers.py`（28 端点）、`server/api/webssh.py`（1 WS）  
**方法**: 8 维清单（认证/越权/注入/路径/凭据/输入/错误/审计）

## 结论

| 级别 | 数量 | 说明 |
|------|------|------|
| P0 | 0 | — |
| P1 | 0 | — |
| P2 | 1 | 已修：`ServerCheck.server_ids` 无上限 → DoS |
| H | 3 | 已记录/接受，见下表 |

**批次结论**: **PASS**（修复已合入工作区）

---

## 端点覆盖

全部 29 个路由均要求 `get_current_admin`（REST）或 WebSSH 专用 JWT（`purpose=webssh` + `server_id` 绑定）。

| 模块 | 端点 | 认证 | 审计 CUD | 备注 |
|------|------|------|----------|------|
| servers | CRUD `/` `/{id}` | JWT | ✓ | `_server_to_dict` 不返明文密码/私钥 |
| servers | `/stats` `/categories` `/logs` | JWT | — | 只读；stats 有 online 封顶 |
| servers | `/import` | JWT | ✓ | 1MB/500 行；CSV 注入防护 `_sanitize_csv_cell` |
| servers | `/batch/*` | JWT | ✓ | `server_ids` max 50；SSH `shlex.quote` |
| servers | `/add-by-ip` `/pending/*` | JWT | ✓（已补 retry 失败） | 轮询失败写 pending + 审计 |
| servers | `/agent-key` `/agent-install-cmd` | JWT + 密码复核 | ✓ | 不回落全局 API_KEY |
| servers | `/install-agent` | JWT | ✓ | 服务端 SSH 可用全局 KEY 作 fallback（H） |
| servers | `/check` | JWT | — | **已修** max 50 server_ids |
| webssh | `/ws/terminal/{id}` | JWT query | connect/disconnect | server_id 绑定；命令审计 + 危险命令检测 |

---

## FINDING 明细

### P2-01 — `POST /api/servers/check` 无 `server_ids` 上限（已修）

- **风险**: 传入数千 ID 触发并行 SSH 探测，资源耗尽。
- **修复**: `ServerCheck.server_ids` 增加 `max_length=50`（与 `BatchAgentAction` 一致）。
- **文件**: `server/api/schemas.py`

### H-01 — WebSSH 遗留 token 无 `tv` 字段时回退 `updated_at` 宽限

- **位置**: `webssh.py` `_verify_webssh_token`
- **影响**: 改密后 5 秒内旧 WebSSH token 仍可能有效（新签发 token 均含 `tv`）。
- **处置**: 接受（单人运维模型）；新 token 路径已安全。

### H-02 — `install-agent` 无 per-server key 时回落 `settings.API_KEY`

- **位置**: `servers.py` `install_agent_remote`
- **影响**: 仅用于 SSH 下发安装命令，不向 API 响应暴露全局 KEY。
- **处置**: 接受；与 Agent 安装运维模型一致。

### H-03 — `retry_pending` 失败与 `delete_pending` 审计字段不完整（已修）

- **修复**: 失败重试写 `retry_pending_server_failed` 审计；删除前读取 pending 写入 `detail`。
- **文件**: `server/api/servers.py`

---

## 安全亮点（无需改动）

- `_server_to_dict`: `password_set` / `ssh_key_private_set` / agent key 预览
- `update_server`: `ALLOWED_FIELDS` 白名单，禁止 mass-assign `agent_api_key`
- `_sudo_wrap`: 临时 sudoers 白名单命令 + 事后清理
- `setup-files-sudo`: 密码经 stdin 喂 `sudo -S`，不进 argv
- WebSSH: token `server_id` 与路径参数必须一致（防 IDOR）
- CSV import: 大小/行数限制 + formula injection 防护

---

## 验证

```bash
.venv/bin/pytest tests/test_credential_poller.py tests/test_security_unit.py -q
```

---

**下一批**: B2 — `sync_v2.py` + `files.py` + `remote_path_validation.py`
