# 审计记录 — files.html + sync_v2.py 全面迭代

## 审计信息

- **日期**: 2026-05-30
- **审计人**: Claude (AI) + 用户确认
- **触发原因**: 文件管理器全面迭代（15项改进）

## 审计范围

| 文件 | 行数 | 状态 |
|------|------|------|
| web/app/files.html | 439 | ☑ 已审 |
| server/api/sync_v2.py | 1200 | ☑ 已审 |
| server/api/schemas.py | 215 | ☑ 已审 |

## 审计8步结果

### Step 1: 登记 ✅
### Step 2: 全文Read ✅
### Step 3: 规则扫描H — 30 项
### Step 4: Closure表

| H-xx | 严重度 | Closure | 说明 |
|------|--------|---------|------|
| H-01 | HIGH | **ACCEPTED_RISK** | 远程路径无限制 — 用户明确决策"不加限制" |
| H-02 | LOW | **FINDING→已修** | Content-Disposition filename sanitize |
| H-03 | LOW | ACCEPTED_RISK | base64 echo 单引号，RFC 4648 字母表安全 |
| H-04 | LOW | FALSE_POSITIVE | upload 路径穿越检查充分 |
| H-05 | N/A | FALSE_POSITIVE | 无 SQL 操作 |
| H-06 | INFO | FALSE_POSITIVE | esc() 覆盖完整，无 XSS |
| H-07 | N/A | FALSE_POSITIVE | 无 HTTP 客户端 |
| H-08 | N/A | FALSE_POSITIVE | 无明文密码 |
| H-09 | N/A | FALSE_POSITIVE | 无硬编码密钥 |
| H-10 | INFO | FALSE_POSITIVE | 审计失败降级合理 |
| H-11 | N/A | FALSE_POSITIVE | JWT 全覆盖 |
| H-12 | LOW | **FINDING→已修** | path 字段加 max_length=4096 |
| H-13 | N/A | FALSE_POSITIVE | 全部有审计日志 |
| H-14 | INFO | FALSE_POSITIVE | Bearer token 免疫 CSRF |
| H-15 | MEDIUM | **FINDING→已修** | download 加 100MB 大小限制 |
| H-16 | LOW | ACCEPTED_RISK | batchDelete is_dir 不影响结果 |
| H-17 | LOW | ACCEPTED_RISK | 竞态概率极低 |
| H-18 | INFO | FALSE_POSITIVE | parseInt 源数据安全 |
| H-19 | N/A | FALSE_POSITIVE | Pydantic 自动校验 |
| H-20 | N/A | FALSE_POSITIVE | JS pop() 安全 |
| H-21 | N/A | FALSE_POSITIVE | 线性遍历无循环风险 |
| H-22 | INFO | FALSE_POSITIVE | async with + finally 双重保护 |
| H-23 | LOW | **FINDING→已修** | 同 H-15，合并修复 |
| H-24 | INFO | FALSE_POSITIVE | async 架构 |
| H-25 | N/A | FALSE_POSITIVE | 无 DB 密集操作 |
| H-26 | INFO | ACCEPTED_RISK | ls 截断 10000 字符足够 |
| H-27 | LOW | **FINDING→已修** | doPreview 保存失败解析错误详情 |
| H-28 | INFO | ACCEPTED_RISK | 错误处理整体一致 |
| H-29 | INFO | **FINDING→已修** | esc() 加注释 |
| H-30 | INFO | ACCEPTED_RISK | ls -la 解析器正确 |

### Step 5: 入口表 ✅
全部 API 端点已检查（download/read-file/write-file/browse/file-ops/upload）。

### Step 6: 输入→Sink ✅
所有用户输入路径已追踪：
- download: path → sftp.stat → StreamingResponse
- read-file: path → stat -c%s → cat
- write-file: path + content → base64 + tee
- file-ops: path → shlex.quote → SSH exec
- upload: remote_path + filename → SFTP put

### Step 7: 归类

```
web/app/files.html                  439行  10H  2FINDING → 0FINDING
server/api/sync_v2.py              1200行  12H  3FINDING → 0FINDING (1 ACCEPTED_RISK)
server/api/schemas.py               215行   8H  1FINDING → 0FINDING
──────────────────────────────────────────────────────────────────
总计                                  6 FINDING → 0FINDING (全部已修或 ACCEPTED_RISK)
```

### Step 8: DoD ✅

## FINDING 列表

| 编号 | 严重度 | 描述 | 修复方式 |
|------|--------|------|----------|
| H-01 | HIGH | 远程端点无路径限制 | ACCEPTED_RISK — 用户决策 |
| H-15 | MEDIUM | download 无大小限制 | 加 100MB stat.size 检查 → 413 |
| H-02 | LOW | Content-Disposition 头注入 | re.sub 替换特殊字符 |
| H-12 | LOW | path 无 max_length | 三个 schema 加 max_length=4096 |
| H-27 | LOW | doPreview 保存错误丢失详情 | 解析 wr.json() 显示 detail |
| H-29 | INFO | esc() 缺注释 | 加 /** HTML-escape */ 注释 |

## 结论

☑ 审计通过，6 FINDING 全部已处理（5 修复 + 1 ACCEPTED_RISK），0 遗留，可部署
