Files
root 8cdf8b44fa docs: refresh public docs for current codebase, add SECURITY.md
- README: real counts (44 commands, 61 integration asserts, demo=25 records
  + 4 semesters + 7 attachments), add resume/assessment module features,
  env vars incl. LSKY, doc navigation table, done-roadmap items checked
- docs/api.md: /auth/logout, admin users/demo-rebuild/sync-lsky routes,
  attachment thumb/download channels, profile_upsert top-key merge
  semantics, full footprint_list query reference, 44-command table
- sync-server/README: replace stale ADMIN_TOKEN/X-Admin-Token admin section
  (actual is_admin Bearer model), add go-live checklist, backup note for WAL
- CHANGELOG: add Unreleased section (resume/assessment modules, security
  fixes, perf tuning)
- CONTRIBUTING: 61 asserts, security-sensitive-change guidance, perf baseline
  table, security issue routing
- docs/SECURITY.md: new - report channel, threat model table, hardening
  summary, known tradeoffs
- LICENSE: ensure MIT file matches README badge
2026-10-17 22:27:56 +08:00

43 lines
3.1 KiB
Markdown
Raw Permalink 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.
# 安全说明
## 漏洞报告
发现安全问题请**不要**直接开公开 Issue(可能包含可利用细节)。联系渠道:
- 仓库主页留下联系方式的维护者(站内私信 / Issues 留言板)
- 紧急情况可直接在描述安全隐患的前提下开 Issue 标注 `security`,我们会尽快下线和修复
处理流程:收到报告 → 48 小时内确认 → 评估影响并给出缓解策略 → 修复发版 → 在 `CHANGELOG.md` 的 `Security` 段致谢公示。
## 安全模型(威胁模型摘要)
数据全走 HTTPS + Bearer Token,服务器为多用户托管形态,按用户强制隔离——信任边界假设
「攻击者 = 其他注册用户 / 网络中间人 / 触碰 GET 接口的匿名流量」。
| 面 | 现状 |
|---|---|
| 认证算法 | scrypt(随机 16B 盐)+ `timingSafeEqual`,官方 crypto 原语,无自造算法 |
| Token | 服务端 32 字节随机 hex 存储 + 365 天过期;登录后同设备复用 device_id;支持 `/auth/logout` 服务端吊销 |
| 类似爆破的防护 | 登录:同 IP+用户名连续失败 5 次 → 冷却 10 分钟(进程内计数) |
| 按用户数据隔离 | `commandsFor(user_id)` 每用户一份独立 `users/<uid>.db`;跨库读取天然命中"不存在",实测经 /api 与 /sync 均无法跨读 |
| 管理 API | 统一双重校验:登录态 + is_admin;自删与"最后管理员"禁删 |
| SQL 注入 | 全部参数化;`ORDER BY` 走白名单(`SORTS` 表);FTS MATCH 参数传入、字符串仅做双引号包裹 |
| 路径注入/XSS | 上传文件名剥离 `\\/:*?"<>|` + UUID 前缀;附件文件名以 **SHA-256 命名**(无文件系统注入位);前端 `dangerouslySetInnerHTML` 有且仅两处(一处全转义、一处白名单净化 docx/xlsx 预览) |
| 注册准入 | `REGISTER_ENABLED`、`INVITE_CODE`(或管理页动态码)、`MAX_USERS` 三道门控,服务端强制(客户端传的 `seed` 播种标志一律剥离,防止绕过邀请码/配额/自动升级管理员规则) |
| 附件上传 | SHA-256 声明校验 + 100MB 上限;下载统一 `Cache-Control: private, immutable`(跨账号缓存隔离) |
| 客户端依赖 | 服务器**零 npm 依赖**(仅 Node 内置模块),规避供应链攻击面 |
| CORS | `Access-Control-Allow-Origin: *`。凭据仅 localStorage Bearer、不用 Cookie,不放大 CSRF 面;如有同源严格化诉求欢迎提案 |
| 审计日志 | 图床清理、用户删除、demo 重建等敏感操作写标准日志(容器 stdout) |
## 已知设计取舍
- Token 存放浏览器 `localStorage`(XSS 可及):与多端 token 缓存目录一致;服务端可能追加 CSP 响应头、可加入 HttpOnly Cookie 会话机制(改动契约,暂未引入)
- 限速是进程内存态,重启清零;RLS 想要更强的反爆破可以套容器内的 fail2ban / Cloudflare 规则
- 备份文件内含用户档案明文,请按敏感数据管理
## 上线运维要点(契约要求)
- 首个真实账号注册后关闭 `REGISTER_ENABLED`,改掉 `INVITE_CODE` 示例默认值
- `./data/` 目录备份(含 `-wal`/`-shm`)
- 服务端公网面只暴露 443(Caddy TLS 到 sync-server)