fix(security): implement all 15 security fixes from penetration test V1
Security audit (2026-03-31): 5 HIGH + 10 MEDIUM issues, all fixed. HIGH: - H1: JWT password_version mechanism (pwv in Claims, middleware verification, auto-increment on password change) - H2: Docker saas port bound to 127.0.0.1 - H3: TOTP encryption key decoupled from JWT secret (production bailout) - H4+H5: Tauri CSP hardened (removed unsafe-inline, restricted connect-src) MEDIUM: - M1: Persistent rate limiting (PostgreSQL rate_limit_events table) - M2: Account lockout (5 failures -> 15min lock) - M3: RFC 5322 email validation with regex - M4: Device registration typed struct with length limits - M5: Provider URL validation on create/update (SSRF prevention) - M6: Legacy TOTP secret migration (fixed nonce -> random nonce) - M7: Legacy frontend crypto migration (static salt -> random salt) - M8+M9: Admin frontend: removed JS token storage, HttpOnly cookie only - M10: Pipeline debug log sanitization (keys only, 100-char truncation) Also: fixed CLAUDE.md Section 12 (was corrupted), added title.rs middleware skeleton, fixed RegisterDeviceRequest visibility.
This commit is contained in:
137
CLAUDE.md
137
CLAUDE.md
@@ -355,84 +355,71 @@ refactor(store): 统一 Store 数据获取方式
|
||||
|
||||
***
|
||||
|
||||
|
||||
## 12. 安全注意事项
|
||||
|
||||
</section>
|
||||
|
||||
< + + 寜### 安全注意事项
|
||||
|`
|
||||
|--- 不在代码中硬编码密钥`
|
||||
| - 敄 操作需要确认
|
||||
` - 不在代码中硬编码密V Token/ API |
|
||||
| - 保留操作审计日志
|
||||
` - 用户输入必须验证` ` - 敄 就环境变量 `ZCLAW_SAAS_DEV` 模式放宽安全限制(开发环境设 `ZCLAW_SAAS_DEV=true`), + ` - **生产环境 TLS 终止**:
|
||||
nginx/caddy 反代向提供 HTTPS**
|
||||
|
|
||||
| - Cookie `Secure` 标记在生产环境设为 true,开发环境设为 false(仅 臉 TOTP 加密密钥 `ZCLAW_TOTP_ENCRYPTION_KEY` 必须设置(64 字符 hex)
|
||||
密钥) |
|
||||
| - **Cookie SameSite=Strict** 鰲止 CSRF)` |
|
||||
| - Refresh Token 轮换: 退出时,DB 撤销为关联, 旧 token` |
|
||||
| + **Rotation 校验已使用 token 是否已撤销` |
|
||||
| + **Logout 时撤销 refresh token` |
|
||||
| - **TLS**: 生产环境必须使用反向代理 (nginx/caddy) 提供 HTTPS, |
|
||||
| - Cookie Secure 标记: 开发环境 false, 生产 true` |
|
||||
|
||||
| + + | **配置说明** |
|
||||
| - saas-config.toml 支持 `${ENV_VAR}` 稡式环境变量插值,如 `${DB_PASSWORD}` |
|
||||
| - `ZCLAW_DATABASE_URL` 茉境变量覆盖 |
|
||||
优先级最高) |
|
||||
| - **Auth**: /api/auth/login` - 5次/分钟/IP (防暴力破解) |
|
||||
| - `/api/auth/register` - 3次/小时/IP (防刷注册) |
|
||||
| - 公共端点默认 20次/分钟/IP (防滥用) |
|
||||
| - JWT 寰钥: `#[cfg(debug_assertions)]` 保护 fallback,release 枋 | ` bail` 拒绝启动` | - TOTP 加密密钥: AES-256-GCM 加密, 支持 SHA-256 崾生 JWT 密钥派生` |
|
||||
- Logout 撤销: refresh token 到 DB 栘 UPDATE` |
|
||||
| - Cookie: Secure 标志: 开发环境 false, 生产 true
|
||||
|
|
||||
| + + `SameSite=Strict` + 跨站 CSRF + SSL ( CORS) |
|
||||
| + | TLS 终止:: nginx/caddy 反向代理提供 HTTPS`, 或 |
|
||||
生产环境日志写入 WAF - | | **TLS 终止说明**: | 反向代理实现 HTTPS, | Axum 服务不负责 TLS 配置、 |
|
||||
|
||||
`saas-config.toml.example` 更新安全说明 |
|
||||
| | 密钥管理 | 甤境变量引用 (`${DB_PASSWORD}` 等) |
|
||||
数据库密码) | | TOML 解析支持 `${VAR}` 稡式环境变量插值, | | 通过 `ZCLAW_DATABASE_URL` 猯变量完整覆盖 (优先级最高) |
|
||||
|
||||
| - JWT fallback key | `#[cfg(debug_assertions)]` 保护 fallback,release 拒绝启动` | - TOTP/API Key 加密: `AES-256-GCM`, 支持 SHA-256 派生 JWT 密钥派生` | - Logout 时撤销 refresh token 到 DB (`used_at IS NULL` 切 `revoked`) + rotation 校验已撤销的旧 token` | - Cookie Secure: 开发环境 false, 生产 true | `SameSite=Strict` + 跨站 CSRF + SSR CORS 白名单 + `X-Request头 + 请求日志 | |
|
||||
|
||||
| - **TLS**: 生产环境必须使用反向代理 (nginx/caddy) 提供 HTTPS, | - **生产环境日志写入 WAF - | |
|
||||
| - **配置说明**: `saas-config.toml` 支持 `${ENV_VAR}` 稡式环境变量插值, | 文件模板已示例已更新 |
|
||||
| - `ZCLAW_SAAS_JWT_SECRET` | JWT 签名密钥 (至少 32 字符随机字符串) | | | TOTP 加密密钥 `ZCLAW_TOTP_ENCRYPTION_KEY` | TOTP 加密密钥 (hex 编码, 64 字符) | |
|
||||
| | SAAS 配置环境变量 | `ZCLAW_SAAS_DEV` 开发环境 |
|
||||
| `ZCLAW_SAAS_DEV=true` 放宽安全限制 (开发环境: | | 公共端点请求限流 |
|
||||
| - 公共端点限流 & login/register) | refresh/logout | 默认 | `ZCLAW_SAAS_DEV` 不设置) |
|
||||
| | **Cookie**: HttpOnly + Secure + SameSite=Strict + 路径="/api" + "/api/v1/auth" + `Secure` 仅在生产环境为 true |
|
||||
|
||||
| | **TLS**: 反向代理** 提供 HTTPS 终止** | 反向代理(如 nginx/caddy)配置上游 → [SSL 终止 (`proxy downgrade`) |
|
||||
| **Cookie**: Secure 标记仅在开发环境 (`ZCLAW_SAAS_DEV=true`) 设为 false(不强制 HTTPS),生产环境设为 true |
|
||||
|
||||
| - **环境变量模板**: | | 瘾境命令 |
|
||||
| - `DB_PASSWORD` | 数据库密码 |
|
||||
| - `ZCLAW_DATABASE_URL` | 完整数据库连接 URL |
|
||||
| - `ZCLAW_SAAS_JWT_SECRET` | JWT 签名密钥 (≥ 32 字符) |
|
||||
| - `ZCLAW_TOTP_ENCRYPTION_KEY` | TOTP/API Key 加密密钥 (64 hex) |
|
||||
| - `ZCLAW_ADMIN_USERNAME` | 初始管理员用户名 |
|
||||
| - `ZCLAW_ADMIN_PASSWORD` | 初始管理员密码 |
|
||||
| - `ZCLAW_SAAS_DEV` | 开发模式标志 (true=开发, false=生产) |
|
||||
| - **生产环境清单单** |
|
||||
| | nginx/caddy 配置反向代理 + HTTPS |
|
||||
| | 确保设置 `ZCLAW_SAAS_DEV=false`(或不设置) |
|
||||
| | 启用 CORS 白名单 | | | `cors_origins` 匇向实际域名 |
|
||||
| | Cookie Secure=true + HttpOnly=true + SameSite=Strict |
|
||||
| - JWT 寋名密钥 >= 32 字符随机字符串 |
|
||||
| - 数据库密码通过 `${DB_PASSWORD}` 引用 | |
|
||||
|
||||
| **部署命令** (参考) |
|
||||
| | 设置环境变量: `export DB_PASSWORD=your_password` |
|
||||
| | `export ZCLAW_SAAS_JWT_SECRET=$(openssl rand -hex 32)` |
|
||||
| | `cp saas-config.toml.example saas-config.toml` |
|
||||
| | 编辑 saas-config.toml 填入实际数据库 URL |
|
||||
| | `cargo build --release -p zclaw-saas` |
|
||||
| | 启动服务: `./zclaw-saas` |- 不在代码中硬编码密钥
|
||||
- 不在代码中硬编码密钥
|
||||
- 用户输入必须验证
|
||||
- 敏感操作需要确认
|
||||
- 保留操作审计日志
|
||||
- 环境变量 `ZCLAW_SAAS_DEV` 模式放宽安全限制(开发环境设 `ZCLAW_SAAS_DEV=true`)
|
||||
|
||||
### 认证安全
|
||||
|
||||
- **JWT password_version**: 密码修改后自动使所有已签发的 JWT 失效(Claims 含 `pwv`,中间件比对 DB)
|
||||
- **账户锁定**: 5 次登录失败后锁定 15 分钟
|
||||
- **邮箱验证**: RFC 5322 正则 + 254 字符长度限制
|
||||
- **JWT 密钥**: `#[cfg(debug_assertions)]` 保护 fallback,release 模式 `bail` 拒绝启动
|
||||
- **TOTP 加密密钥**: 生产环境强制独立 `ZCLAW_TOTP_ENCRYPTION_KEY`(64 字符 hex),不从 JWT 密钥派生
|
||||
- **TOTP/API Key 加密**: AES-256-GCM + 随机 Nonce
|
||||
- **密码存储**: Argon2id + OsRng 随机盐
|
||||
- **Refresh Token 轮换**: 单次使用,Logout 时撤销到 DB,rotation 校验已撤销的旧 token
|
||||
|
||||
### 网络安全
|
||||
|
||||
- **Cookie**: HttpOnly + Secure + SameSite=Strict + 路径作用域
|
||||
- **Cookie Secure**: 开发环境 false,生产 true
|
||||
- **CORS**: 生产强制白名单,缺失拒绝启动
|
||||
- **TLS**: 反向代理(nginx/caddy)提供 HTTPS 终止,Axum 不负责 TLS
|
||||
- **Docker**: SaaS 端口绑定 `127.0.0.1`,仅通过 nginx 反代访问
|
||||
- **XFF**: 仅信任配置的代理 IP
|
||||
|
||||
### 限流
|
||||
|
||||
- `/api/auth/login` — 5次/分钟/IP(防暴力破解)+ 持久化到 PostgreSQL
|
||||
- `/api/auth/register` — 3次/小时/IP(防刷注册)
|
||||
- 公共端点默认 20次/分钟/IP(防滥用)
|
||||
|
||||
### 前端安全
|
||||
|
||||
- **Admin Token**: HttpOnly Cookie 传递,JS 不存储/读取 token
|
||||
- **Tauri CSP**: 移除 `unsafe-inline` script,`connect-src` 限制为 `http://localhost:*` + `https://*`
|
||||
- **Pipeline 日志**: Debug 日志截断 + 仅记录 keys 不记录 values
|
||||
|
||||
### 环境变量
|
||||
|
||||
| 变量 | 用途 |
|
||||
|------|------|
|
||||
| `DB_PASSWORD` | 数据库密码 |
|
||||
| `ZCLAW_DATABASE_URL` | 完整数据库连接 URL(优先级最高) |
|
||||
| `ZCLAW_SAAS_JWT_SECRET` | JWT 签名密钥 (>= 32 字符) |
|
||||
| `ZCLAW_TOTP_ENCRYPTION_KEY` | TOTP/API Key 加密密钥 (64 hex) |
|
||||
| `ZCLAW_ADMIN_USERNAME` | 初始管理员用户名 |
|
||||
| `ZCLAW_ADMIN_PASSWORD` | 初始管理员密码 |
|
||||
| `ZCLAW_SAAS_DEV` | 开发模式标志 (true=开发, false=生产) |
|
||||
|
||||
`saas-config.toml` 支持 `${ENV_VAR}` 模式环境变量插值。
|
||||
|
||||
### 生产环境清单
|
||||
|
||||
- [ ] nginx/caddy 配置反向代理 + HTTPS
|
||||
- [ ] 确保设置 `ZCLAW_SAAS_DEV=false`(或不设置)
|
||||
- [ ] 启用 CORS 白名单(`cors_origins` 配置实际域名)
|
||||
- [ ] Cookie Secure=true + HttpOnly=true + SameSite=Strict
|
||||
- [ ] JWT 签名密钥 >= 32 字符随机字符串
|
||||
- [ ] `ZCLAW_TOTP_ENCRYPTION_KEY` 独立设置
|
||||
- [ ] 数据库密码通过 `${DB_PASSWORD}` 引用
|
||||
|
||||
### 完整审计报告
|
||||
|
||||
参见 `docs/features/SECURITY_PENETRATION_TEST_V1.md`
|
||||
|
||||
Reference in New Issue
Block a user