# 安全检查清单

Web 应用安全的快速参考。可与 `security-and-hardening` skill 配合使用。

## 目录

- [提交前检查](#提交前检查)
- [认证](#认证)
- [授权](#授权)
- [输入校验](#输入校验)
- [安全 headers](#安全-headers)
- [CORS 配置](#cors-配置)
- [数据保护](#数据保护)
- [依赖安全](#依赖安全)
- [错误处理](#错误处理)
- [OWASP Top 10 快速参考](#owasp-top-10-快速参考)

## 提交前检查

- [ ] 代码里没有 secrets（`git diff --cached | grep -i "password\|secret\|api_key\|token"`）
- [ ] `.gitignore` 覆盖了：`.env`、`.env.local`、`*.pem`、`*.key`
- [ ] `.env.example` 使用的是占位值（不是实际 secrets）

## 认证

- [ ] 密码使用 bcrypt（≥12 rounds）、scrypt 或 argon2 哈希
- [ ] Session cookie：`httpOnly`、`secure`、`sameSite: 'lax'`
- [ ] 已配置 session 过期时间（合理的 max-age）
- [ ] 登录 endpoint 有 rate limit（≤10 次 / 15 分钟）
- [ ] 密码重置 token：有时效（≤1 小时）、只能用一次
- [ ] 多次失败后有账号锁定（可选，带通知）
- [ ] 对敏感操作支持 MFA（可选但推荐）

## 授权

- [ ] 每个受保护 endpoint 都检查认证
- [ ] 每个资源访问都检查 ownership / role（防 IDOR）
- [ ] Admin endpoint 需要 admin 角色校验
- [ ] API key 只赋最小必要权限
- [ ] JWT token 已验证（签名、过期、issuer）

## 输入校验

- [ ] 所有用户输入都在系统边界校验（API route、form handler）
- [ ] 校验使用 allowlist（而不是 denylist）
- [ ] 字符串长度有限制（min / max）
- [ ] 数值范围有限制
- [ ] Email、URL、日期格式用合适的库校验
- [ ] 文件上传：限制类型、大小，并验证内容
- [ ] SQL 查询参数化（不要字符串拼接）
- [ ] HTML 输出编码（使用框架自动转义）
- [ ] 跳转前先验证 URL（防 open redirect）

## 安全 headers

```text
Content-Security-Policy: default-src 'self'; script-src 'self'
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-XSS-Protection: 0  (已禁用，依赖 CSP)
Referrer-Policy: strict-origin-when-cross-origin
Permissions-Policy: camera=(), microphone=(), geolocation=()
```

## CORS 配置

```typescript
// 限制性配置（推荐）
cors({
  origin: ['https://yourdomain.com', 'https://app.yourdomain.com'],
  credentials: true,
  methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
  allowedHeaders: ['Content-Type', 'Authorization'],
})

// 生产环境绝对不要这样：
cors({ origin: '*' })  // 允许任意 origin
```

## 数据保护

- [ ] 敏感字段不出现在 API response 里（`passwordHash`、`resetToken` 等）
- [ ] 敏感数据不写进日志（密码、token、完整信用卡号）
- [ ] PII 如有法规要求则加密存储
- [ ] 所有外部通信都走 HTTPS
- [ ] 数据库备份已加密

## 依赖安全

```bash
# 审计依赖
npm audit

# 能自动修的尽量自动修
npm audit fix

# 检查关键漏洞
npm audit --audit-level=critical

# 保持依赖更新
npx npm-check-updates
```

## 错误处理

```typescript
// 生产环境：返回通用错误，不暴露内部细节
res.status(500).json({
  error: { code: 'INTERNAL_ERROR', message: 'Something went wrong' }
});

// 生产环境绝对不要这样：
res.status(500).json({
  error: err.message,
  stack: err.stack,         // 暴露内部细节
  query: err.sql,           // 暴露数据库细节
});
```

## OWASP Top 10 快速参考

| # | 漏洞 | 防护 |
|---|---|---|
| 1 | Broken Access Control | 每个 endpoint 都做 auth 检查和 ownership 验证 |
| 2 | Cryptographic Failures | HTTPS、强哈希、代码里不放 secrets |
| 3 | Injection | 参数化查询、输入校验 |
| 4 | Insecure Design | 威胁建模、规格驱动开发 |
| 5 | Security Misconfiguration | 安全 headers、最小权限、审计依赖 |
| 6 | Vulnerable Components | `npm audit`、保持依赖更新、尽量少依赖 |
| 7 | Auth Failures | 强密码、rate limiting、session 管理 |
| 8 | Data Integrity Failures | 验证更新 / 依赖、签名制品 |
| 9 | Logging Failures | 记录安全事件，不记录 secrets |
| 10 | SSRF | 验证 / allowlist URL，限制外部请求 |
