记录 4 路并行审计发现、修复清单、刻意不改项及理由、安全结论、通用教训。 配套 cluster-recall #5785。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
39 lines
3.4 KiB
Markdown
39 lines
3.4 KiB
Markdown
# 全面审计报告 — 2026-07-21
|
||
|
||
> 方法: 4 路并行子代理审计(core / modules / wiring+UI / security),逐条交叉验证后修复。
|
||
> 提交: `fix/audit-hardening` (db73b34) | cluster-recall #5785
|
||
> 验证闭环: `node --check` 语法全检 + `yinji-cli` 冒烟/状态/批量/端到端 + UI 截图 + CSP 违规检查
|
||
|
||
## 已修复(8 类, 11 文件)
|
||
|
||
| 严重度 | 文件 | 缺陷 | 修复 |
|
||
|--------|------|------|------|
|
||
| HIGH | main.js:1071 | 键盘快捷键不判焦点: 坐标框 Backspace 删印章、方向键移印章、旋转框输不了负号、文本框 Ctrl+C/V/S 被劫持 | handler 开头加焦点守卫(INPUT/TEXTAREA/SELECT/contenteditable/isComposing → return) |
|
||
| HIGH | seal-library.js:19 | `getSavedSeals` 不校验数组,脏 localStorage 打死印章库读/写/渲染 | `Array.isArray` 校验 + `isValidSeal` 逐项过滤 + 格式异常自动重置 |
|
||
| MED | seal-library.js:260 | `loadAndApplySeal` 无 onerror + 成功 toast 在 onload 外同步弹 | toast 移入 onload、补 onerror、handler 先于 src 赋值 |
|
||
| MED | canvas-manager.js:113 / context-menu.js:42 | 右键不选中对象 → 菜单不出现或作用于旧对象 | 开 `fireRightClick`/`stopContextMenu`,菜单前 `findTarget` 命中置活动对象 |
|
||
| MED | responsive.js:70-139 | 触摸手势死代码(`_canvas` 从不赋值) + body 全子树 MutationObserver 常驻空转 | 移除死代码链(fabric 自带触摸兜底),保留响应式布局 |
|
||
| LOW | exporter/batch-processing/batch-operations/settings (×5) | blob URL `click()` 后立即 revoke → 部分浏览器下载失败 | 延迟 `setTimeout(revoke, 1000)` |
|
||
| LOW | batch-processing.js:253 | 下载名 `.replace('.pdf')` 首次匹配+区分大小写+未 sanitize | 统一 `generateSafeExportFilename` |
|
||
| MED(加固) | index.html:9 / security.js | CSP 缺 object/frame 限制、无转义助手 | CSP 加 `object-src 'none'; frame-ancestors 'none'`;补 `escapeHtml()` |
|
||
| INFO | tmp-global-patch-test-a.js | 根目录遗留测试残file | 删除 |
|
||
|
||
## 刻意不改(附理由)
|
||
|
||
- **exporter 恒 `degrees(0)`**: 旋转烘焙进位图(`getRotatedCroppedImage`) + 对象 `lockRotation:true`,正常使用不可能产生非零 angle,当前不可触发。
|
||
- **state.js `setState` 浅拷贝**: previousState 与集合/数组字段共享引用,但 batch-operations 已用 `new Set(...)` 防御拷贝规避。
|
||
- **seal id `Date.now()` 毫秒碰撞**: 手动操作极难触发。
|
||
- **pdf.js `isEvalSupported`**: CSP 无 `unsafe-eval`,eval 本就被拦。
|
||
- **SVG 白名单(image/svg+xml)**: 经确认非 XSS 向量(仅经 `<img>`/fabric image 静态渲染,不执行脚本),保留功能。
|
||
- **移除 `script-src 'unsafe-inline'`**: 需搬 index.html 内联 lucide 初始化脚本,有回归风险,建议后续单独一项处理。
|
||
|
||
## 安全结论
|
||
|
||
未发现任何可实际利用的 XSS/注入。防护可信,但可信来自"全程用 `textContent` 而非 `innerHTML` 渲染不可信数据(文件名/印章名/签名/toast/dialog)"的编码纪律,而非集中转义工具。所有 innerHTML 均为开发者硬编码静态模板。fabric 反序列化为自写、只吃应用自身内存对象,不吃外部不可信 JSON。
|
||
|
||
## 通用教训(见 cluster-recall #5785)
|
||
|
||
1. 全局键盘快捷键处理器必须判 `e.target` 是否输入控件 + `e.isComposing`。
|
||
2. localStorage 读取 `JSON.parse` 后必须校验类型(`Array.isArray`)并逐项过滤脏数据。
|
||
3. blob URL 下载应延迟 revoke。
|
||
4. `image.onload` 必配 `onerror`,成功提示放 onload 内。
|