Skip to content

Security

one-ea edited this page Apr 25, 2026 · 3 revisions

🛡️ 安全设计

Monolith 共部署 14 项主动安全加固,覆盖认证、输入、网络、存储、隐私五个层面。

与仓库根目录 SECURITY.md 同步。


1. 认证与会话

JWT 鉴权

  • 所有 /api/admin/* 路由强制验证 Bearer Token
  • HS256 算法,默认 8 小时过期
  • JWT_SECRET 通过 wrangler secret put 注入(≥32 字节)
  • 登出时 token 加入黑名单直到自然过期

登录限流

  • /api/auth/login 限制 5 次 / 15 分钟 / IP
  • 触发后返回 429,建议 fail2ban 配合阻断

单设备登录

新登录会撤销旧 token,防止 token 泄漏后被并行使用。


2. 输入与输出

XSS 防护(双层)

  • 前端: 评论与文章渲染前用 DOMPurify 净化
  • 后端: Markdown 转 HTML 后再次 DOMPurify 服务器端净化
  • 严格白名单标签 / 属性

Markdown URI 过滤

阻止 javascript:, data:, vbscript: 等恶意协议链接。仅放行 http(s)://, mailto:, tel:, 站内相对路径。

SQL 注入防护

  • Drizzle ORM 全部参数化查询
  • 禁止 sql.raw() 字符串拼接(ESLint 规则强制)
  • 三套 schema 同步避免某后端漏改

评论邮箱隔离

  • 用户填写的邮箱只用于头像 Gravatar 哈希
  • 后台管理界面不展示原邮箱(防泄漏)
  • 仅 OPENAPI 审计日志记录哈希值

3. 网络与边缘

CORS 严格控制

const allowedOrigins = env.CORS_ALLOWED_ORIGINS?.split(',') ?? [];
  • 默认仅允许 Pages 自身域名
  • 自定义域名需显式加入 CORS_ALLOWED_ORIGINS

安全响应头

client/functions/_middleware.ts 与 Workers 双层注入:

Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
Content-Security-Policy: default-src 'self'; ...

SSRF 防护

导入器 fetch 前校验目标 IP:

  • 拒绝 RFC1918 私网段 (10/8, 172.16/12, 192.168/16)
  • 拒绝 127/8, 169.254/16 (link-local), 224/4 (multicast)
  • 拒绝 localhost / 元数据服务地址

速率限制(公开写入)

  • 评论:3 次 / 5 分钟 / IP
  • Reaction:10 次 / 1 分钟 / IP+UA

4. 存储与密钥

密钥管理

名称 来源 用途
ADMIN_PASSWORD wrangler secret put 唯一管理员密码
JWT_SECRET wrangler secret put (≥32B) JWT 签名
REACTION_SALT wrangler secret put 反应指纹哈希盐

⚠️ 禁止把 secret 写入 .env 提交。.gitignore 已屏蔽 .dev.vars / .env*

反应指纹

const fingerprint = sha256(`${ip}:${ua}:${REACTION_SALT}`);
  • REACTION_SALT 缺失时拒绝接受反应(防匿名指纹推算)
  • 32 字节随机盐,每个项目独立

备份保护

  • R2 backups/ 目录通过 /cdn/backups/* 路径暴露
  • 强制 JWT 鉴权(仅管理员可下载)
  • 备份文件自动 gzip 压缩

数据库防注入

  • 全部使用 Drizzle ORM 参数化
  • 三端 schema 同步(D1/Turso/PostgreSQL)
  • 外键 ON DELETE/UPDATE 模式必须明确指定

5. 隐私合规

Cookie 同意

  • 首次访问展示 GDPR 风格同意横幅
  • 拒绝则禁用所有非必要 cookie / localStorage
  • 选择持久化于 localStorage.cookie_consent

隐私政策

  • /privacy 路由提供静态隐私政策页
  • 仓库内置 PRIVACY.md,Pages 与 GitHub 双渠道公示

Sourcemap 关闭

生产构建禁用 sourcemap,避免源码暴露:

// vite.config.ts
build: { sourcemap: false }

浏览器指纹最小化

  • 不部署 Google Analytics / 第三方 tracker
  • 自研 Analytics 仅记录 path / referrer / UA family(不记录精确 UA)

自动化扫描

CI 静态扫描

工具 范围 触发
CodeQL TS/JS 漏洞模式 push + 每周
Dependabot npm 依赖 CVE 每日
ESLint 代码安全规则 (no-eval, no-script-url) push + PR

依赖审计

npm audit --production
npm outdated

CI 中失败会阻塞合并。


报告漏洞

发现漏洞请按 SECURITY.md 流程上报:

  1. 不要公开 Issue
  2. 通过 GitHub Security Advisories 或仓库联系方式发送
  3. 48 小时内确认 / 7 天评估 / 14-30 天修复 / 30 天披露

延伸阅读

Clone this wiki locally