mcpField
S
security-operations-deployment

security-operations-deployment

github.com/harperaa安全19164 次安装45 周前更新
代码仓库

关于 security-operations-deployment

security-operations-deployment 是一项提供 Web 应用安全与部署实用指导的技能,涵盖中间件选择、密钥管理、部署前检查和上线后监控。

主要功能

  1. 01速率限制与 CSRF 中间件使用指导
  2. 02环境变量和密钥管理
  3. 03部署前安全检查清单
  4. 04上线后指标与日志监控
  5. 05安全事件响应优先级

适用场景

  1. 01为 API 路由选择防护措施
  2. 02准备生产环境密钥和配置
  3. 03部署前检查应用安全
  4. 04监控身份验证、CSRF 和速率限制事件

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/harperaa/secure-claude-skills --skill security-operations-deployment

安装后在 Claude Code 中输入/security-operations-deployment确认已加载。

详细介绍

安全运维与部署

何时应用各中间件 - 决策指南

withRateLimit() - 适用于:

✅ 始终应用于:

  • 任何可能遭到滥用的路由(垃圾信息、暴力破解)
  • 类似登录的操作(即使由 Clerk 处理身份验证)
  • 数据创建/修改端点
  • 联系/支持表单端点
  • Webhook(以防止 DoS)
  • 文件上传端点
  • 搜索端点
  • 数据导出端点
  • 任何耗费资源的 AI/API 操作
  • 报告生成
  • 批量操作

❌ 通常不需要用于:

  • 静态资源请求(由 CDN 处理)
  • 仅读取公开数据的简单 GET 端点
  • 健康检查端点
  • 已受身份验证速率限制保护的端点
withCsrf() - 适用于:

✅ 始终应用于:

  • 所有 POST/PUT/DELETE 操作
  • 任何会更改状态的操作
  • 表单提交
  • 账户修改
  • 支付操作
  • 数据删除操作

❌ 以下情况跳过:

  • GET 请求(只读操作)
  • 公开的只读端点
  • Webhook(改用签名验证)
组合使用两个中间件

为获得最大程度的保护:

// Order matters: rate limit first, then CSRF
export const POST = withRateLimit(withCsrf(handler));

顺序为何重要:

  1. 先运行速率限制,以尽早拦截过多请求
  2. 对通过速率限制的请求运行 CSRF 验证
  3. 效率更高:无需对受速率限制的请求浪费资源进行 CSRF 验证

决策矩阵:

路由类型速率限制CSRF身份验证
公开表单提交✅ 是✅ 是❌ 否
受保护的数据修改✅ 是✅ 是✅ 是
公开只读 API❌ 否❌ 否❌ 否
受保护的只读 API✅ 视情况而定❌ 否✅ 是
Webhook 端点✅ 是❌ 否✅ 签名
文件上传✅ 是✅ 是✅ 是

环境变量与密钥

本项目所需的环境变量

开发环境(.env.local - 切勿提交):

# CSRF Protection
# Generate with: node -p "require('crypto').randomBytes(32).toString('base64url')"
CSRF_SECRET=<32-byte-base64url-string>
SESSION_SECRET=<32-byte-base64url-string>

# Clerk Authentication (from Clerk dashboard)
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_test_...
CLERK_SECRET_KEY=sk_test_...
NEXT_PUBLIC_CLERK_FRONTEND_API_URL=https://your-app.clerk.accounts.dev

# Convex Database (from Convex dashboard)
CONVEX_DEPLOYMENT=dev:...
NEXT_PUBLIC_CONVEX_URL=https://...convex.cloud

# Optional: Stripe (if using direct Stripe, not Clerk Billing)
STRIPE_SECRET_KEY=sk_test_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_test_...

# Optional: Clerk Webhook Secret
CLERK_WEBHOOK_SECRET=whsec_...

生产环境(Vercel/托管平台):

# CSRF Protection (different from dev!)
CSRF_SECRET=<different-32-byte-string>
SESSION_SECRET=<different-32-byte-string>

# Clerk Production Keys
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=pk_live_...
CLERK_SECRET_KEY=sk_live_...
NEXT_PUBLIC_CLERK_FRONTEND_API_URL=https://your-app.clerk.accounts.com

# Convex Production
CONVEX_DEPLOYMENT=prod:...
NEXT_PUBLIC_CONVEX_URL=https://...convex.cloud

# Optional: Stripe Production
STRIPE_SECRET_KEY=sk_live_...
NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=pk_live_...

# Optional: Clerk Webhook Secret (production)
CLERK_WEBHOOK_SECRET=whsec_...
生成密钥
# Generate CSRF_SECRET (32 bytes)
node -p "require('crypto').randomBytes(32).toString('base64url')"

# Generate SESSION_SECRET (32 bytes)
node -p "require('crypto').randomBytes(32).toString('base64url')"
环境变量最佳实践

✅ 应当:

  • 为开发/预发布/生产环境使用不同的密钥
  • 生成强随机密钥(32 字节以上)
  • 将 .env.local 添加到 .gitignore
  • 将生产密钥存储在托管平台的密钥管理器中
  • 每季度轮换密钥
  • 启动时验证所需的环境变量

❌ 切勿:

  • 在代码中硬编码 API 密钥、令牌或其他密钥
  • 将 .env.local 提交到版本控制系统
  • 记录环境变量
  • 在客户端代码中暴露密钥
  • 在 NEXT_PUBLIC_* 变量中使用 .env.local 的值(它们会暴露给浏览器!)
  • 通过电子邮件、Slack 或不安全的渠道分享密钥
启动时验证配置
// lib/config.ts
const requiredEnvVars = [
  'CSRF_SECRET',
  'SESSION_SECRET',
  'NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY',
  'CLERK_SECRET_KEY',
  'NEXT_PUBLIC_CONVEX_URL'
];

export function validateConfig() {
  const missing = requiredEnvVars.filter(v => !process.env[v]);

  if (missing.length > 0) {
    throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
  }

  // Validate secret lengths
  if (process.env.CSRF_SECRET && process.env.CSRF_SECRET.length < 32) {
    throw new Error('CSRF_SECRET must be at least 32 characters');
  }

  if (process.env.SESSION_SECRET && process.env.SESSION_SECRET.length < 32) {
    throw new Error('SESSION_SECRET must be at least 32 characters');
  }
}

// In your app startup (e.g., middleware.ts or layout.tsx)
validateConfig();

部署前安全检查清单

每次部署到生产环境前,请逐项检查:

环境与配置
  • 已在生产环境中设置所有环境变量
  • 已生成并配置 CSRF_SECRET(32 字节以上)
  • 已生成并配置 SESSION_SECRET(32 字节以上)
  • 已配置 Clerk 生产密钥(pk_live_...、sk_live_...)
  • 已配置 Convex 生产部署
  • 已配置 Stripe 实时模式密钥(如果直接使用 Stripe)
  • 未将 .env.local 提交到 git(使用 git status 检查)
  • 开发环境与生产环境使用不同的密钥
依赖项
  • 运行 npm audit --production - 无漏洞
  • 运行 npm outdated - 检查关键安全更新
  • 已将 package-lock.json 提交到 git
  • Next.js 使用最新稳定版(当前为 15.5.4+)
  • 所有关键软件包均已更新
安全功能
  • 已测试 CSRF 保护(参见 security-testing 技能)
  • 已测试速率限制(node scripts/test-rate-limit.js)
  • 已使用恶意输入测试输入验证
  • 已验证安全标头(curl -I https://yourapp.com)
  • 已在生产环境启用 HSTS(中间件会自动启用)
  • 生产环境中的错误消息为通用消息(不包含堆栈跟踪)
身份验证与授权
  • 受保护的路由需要身份验证
  • 访问前检查资源所有权
  • 为高级功能验证订阅状态
  • 验证 Webhook 签名(Clerk、Stripe)
  • 妥善处理会话过期
  • 代码中没有硬编码的凭据
API 安全
  • 所有 POST/PUT/DELETE 路由都启用了 CSRF 保护
  • 所有公开端点都启用了速率限制
  • 使用 Zod schema 验证所有用户输入
  • 使用错误处理工具函数处理所有错误
  • 日志中没有敏感数据(密码、令牌、卡片信息、个人身份信息)
  • 代码中没有硬编码的密钥(请参阅下方的 grep 检查)
支付安全(如适用)
  • 使用 Clerk Billing + Stripe(不直接处理卡片信息)
  • 使用 Svix 签名验证 Webhook
  • 在服务端检查订阅状态
  • 在生产环境中禁用测试模式
  • 不在任何地方记录卡片数据
测试
  • 速率限制测试通过:node scripts/test-rate-limit.js
  • 手动测试 CSRF 保护
  • 使用 XSS 载荷测试输入验证
  • 检查安全标头:curl -I https://yourapp.com
  • 测试身份验证流程
  • 在生产模式下测试错误处理
最终检查
# Check for hardcoded secrets
grep -r "sk_live" . --exclude-dir=node_modules
grep -r "AKIA" . --exclude-dir=node_modules
grep -r "api_key.*=" . --exclude-dir=node_modules

# Verify .env.local not in git
git status | grep .env.local  # Should return nothing

# Run full security audit
npm audit --production
bash scripts/security-check.sh

# Test production build
npm run build
NODE_ENV=production npm start

部署后的安全监控

监控内容
服务端日志(每日)

监控以下可能表示存在攻击的模式:

速率限制违规(HTTP 429):

- Repeated 429 errors from same IP → potential abuse/brute force
- High volume of 429s → possible distributed attack
- 429s on login endpoints → credential stuffing attempt

CSRF 失败(HTTP 403):

- Repeated 403 with "CSRF token invalid" → potential CSRF attack
- Sudden spike in CSRF failures → possible automated attack
- 403s without prior token fetch → attack bypass attempt

身份验证失败(HTTP 401/403):

- 401 spikes → potential brute force on protected endpoints
- 403 spikes → unauthorized access attempts
- Pattern of 401 followed by 403 → enumeration attack

异常错误模式:

- Sudden increase in 500 errors → potential attack or system issue
- 400 errors with validation failures → input attack attempts
- Errors from unusual geographic locations
需要跟踪的指标(每周)

身份验证指标:

  • 每小时身份验证失败次数
  • 账户锁定次数(如已实现)
  • 登录尝试的地理分布
  • 异常登录时间(凌晨 3 点大量登录 = 机器人)

速率限制指标:

  • 每个 IP 的速率限制违规次数
  • 触发速率限制次数最多的 IP
  • 最常触发速率限制的端点
  • 速率限制违规趋势随时间的变化

CSRF 保护指标:

  • CSRF 验证失败次数
  • CSRF 令牌生成率
  • 令牌重用尝试次数
  • 缺少令牌的尝试次数

输入验证指标:

  • 各字段的验证失败次数
  • XSS 尝试模式(输入中的 script 标签)
  • SQL 注入尝试模式
  • 超长输入尝试次数

错误率指标:

  • 各端点的错误率
  • 各 HTTP 状态码的错误率
  • 错误率趋势随时间的变化
  • 错误的地理分布
设置监控
Vercel 日志(内置)
# View logs in Vercel dashboard
https://vercel.com/your-project/logs

# Filter by status code
Status: 429  # Rate limited
Status: 403  # CSRF/Forbidden
Status: 401  # Unauthorized
Clerk 控制面板(身份验证)

在 Clerk 控制面板中监控:

  • 登录失败次数
  • 账户创建率
  • 会话活动
  • 可疑 IP 地址
自定义日志记录
// lib/security-logger.ts
export function logSecurityEvent(event: {
  type: 'RATE_LIMIT' | 'CSRF_FAILURE' | 'AUTH_FAILURE' | 'VALIDATION_FAILURE';
  ip?: string;
  userId?: string;
  endpoint?: string;
  details?: Record<string, any>;
}) {
  const log = {
    timestamp: new Date().toISOString(),
    environment: process.env.NODE_ENV,
    ...event
  };

  // In production, send to logging service
  if (process.env.NODE_ENV === 'production') {
    console.log(JSON.stringify(log));
    // Optional: Send to external service (Datadog, LogRocket, etc.)
  } else {
    console.log('Security Event:', log);
  }
}

// Usage in middleware/routes
if (rateLimitExceeded) {
  logSecurityEvent({
    type: 'RATE_LIMIT',
    ip: clientIp,
    endpoint: request.nextUrl.pathname
  });
}
响应流程

高优先级警报(立即响应):

  • 身份验证失败次数大幅飙升(>100 次/分钟)
  • 来自多个 IP 的 CSRF 失败(协同攻击)
  • 500 错误率突然上升(超过正常水平的 10 倍)
  • 正在利用已知漏洞

中优先级(24 小时内响应):

  • 速率限制违规次数逐渐增加
  • 单个 IP 持续尝试身份验证失败
  • 日志中出现新的错误模式
  • 来自新地理区域的异常流量

低优先级(每周审查):

  • 正常的背景身份验证失败
  • 偶发的速率限制触发
  • 常规的输入验证失败
  • 常见错误模式
自动警报

在托管平台中设置警报:

Vercel:

Alerts → New Alert Rule
- Error rate > 10% for 5 minutes → Email/Slack
- 429 responses > 100/min → Email/Slack
- 500 responses > 50/min → Email/Slack

自定义警报:

// Monitor and alert on patterns
if (rateLimitViolations > THRESHOLD) {
  await sendAlert({
    severity: 'HIGH',
    message: `Rate limit violations: ${rateLimitViolations}/min`,
    ip: attackerIp
  });
}

资源与文档

项目安全文档

实施指南:

  • .claude/skills/security/security-overview/SKILL.md - 整体架构
  • .claude/skills/security/*/SKILL.md - 各项安全功能
  • docs/security/SECURITY_IMPLEMENTATION.md - 完整实施指南
  • README.md - 安全配置部分

安全意识与学习:

  • .claude/skills/security/security-awareness/ - AI 代码漏洞分析
  • .claude/skills/security/security-awareness/awareness-overview/ - 完整安全概述
测试与验证脚本

安全测试:

  • scripts/test-rate-limit.js - 速率限制验证
  • scripts/security-check.sh - 依赖项审计
  • scripts/security-test.sh - 全面的安全测试套件(如已创建)

示例实现:

  • app/api/example-protected/route.ts - 完整安全栈示例
  • app/api/test-rate-limit/route.ts - 速率限制测试端点
  • app/api/csrf/route.ts - CSRF 令牌生成
外部安全资源

OWASP(安全标准):

框架与服务文档:

测试工具:


维护计划

每日
  • 在 Vercel 控制面板中检查错误日志
  • 在 Clerk 控制面板中监控失败的身份验证尝试
  • 查看所有安全警报
每周
  • 运行 npm audit --production
  • 检查 GitHub Dependabot 警报
  • 查看错误日志,查找规律
  • 检查速率限制违规趋势
每月
  • 全面安全审计:bash scripts/security-check.sh
  • 更新依赖项:npm update + 测试
  • 检查并轮换任何已泄露的密钥
  • 重新运行安全测试套件
  • 检查安全标头:https://securityheaders.com/
每季度
  • 轮换 CSRF_SECRET 和 SESSION_SECRET
  • 进行主要框架更新(Next.js、React)
  • 完整渗透测试(手动尝试 XSS、CSRF、绕过身份验证)
  • 检查并更新安全策略
  • 安全意识培训(查看技能)

快速参考命令

# Generate secrets
node -p "require('crypto').randomBytes(32).toString('base64url')"

# Check for vulnerabilities
npm audit --production

# Check for outdated packages
npm outdated

# Run security test suite
node scripts/test-rate-limit.js
bash scripts/security-check.sh

# Check for hardcoded secrets
grep -r "sk_live" . --exclude-dir=node_modules
grep -r "AKIA" . --exclude-dir=node_modules

# Test security headers
curl -I https://yourapp.com

# Verify .env.local not committed
git status | grep .env.local

# Production build test
npm run build
NODE_ENV=production npm start

总结:安全运维原则

🔒 部署前:

  • 检查清单必须 100% 完成
  • npm audit 漏洞数为 0
  • 所有测试均通过
  • 所有环境变量均已配置

🔒 部署后:

  • 每天监控日志
  • 立即响应警报
  • 每周查看指标
  • 每月更新依赖项

🔒 持续执行:

  • 安全工作永无止境
  • 持续关注新漏洞
  • 保持依赖项为最新版本
  • 定期测试安全功能

实施详情请参阅各项安全技能。 漏洞安全意识相关内容请参阅 security-awareness 技能。

评论

支持 Markdown