安全哨兵Skill security-sentinel

安全哨兵技能用于在编写和审查API路由、实施认证授权、处理用户输入、数据库查询、文件操作、管理环境变量和机密、构建支付处理功能、实施会话管理、处理敏感数据或加密等场景下,审计代码以发现安全漏洞。它是支付处理、认证系统和数据处理的关键技能。

安全审计 0 次安装 0 次浏览 更新于 3/2/2026

安全哨兵(World-Class Security Skill)

何时使用

始终在以下情况下使用此技能:

  • 编写/审查API路由(尤其是POST/PATCH/PUT/DELETE)
  • 实施认证或授权
  • 处理用户输入(表单、查询参数、文件上传)
  • 处理数据库查询
  • 处理文件操作
  • 管理环境变量和机密
  • 构建支付处理功能
  • 实施会话管理
  • 处理敏感数据或加密
  • 创建拉取请求之前
  • 部署之前

全面文档

这项技能包括完整的安全参考资料:

📚 核心参考资料(总共10,426行)

  1. owasp-top-10-complete.md(2,133行)- 完整的OWASP Top 10及代码示例

    • A01:访问控制破损(IDOR、路径遍历)
    • A02:加密失败(弱哈希、硬编码机密)
    • A03:注入(SQL、NoSQL、命令注入)
    • A04:不安全设计(竞赛条件、速率限制)
    • A05:安全配置错误(CORS、错误消息)
    • A06:易受攻击的组件(依赖管理)
    • A07:认证失败(弱密码、MFA)
    • A08:完整性失败(供应链、反序列化)
    • A09:日志失败(审计跟踪、监控)
    • A10:SSRF(URL验证、IP阻止)
  2. authentication-patterns.md(1,529行)- 完整的认证指南

    • JWT令牌认证
    • 基于会话的认证
    • 密码哈希(bcrypt、Argon2)
    • 密码重置流程
    • 电子邮件验证
    • 多因素认证(TOTP)
    • OAuth 2.0(GitHub、Google)
    • 无密码认证(魔术链接)
    • 刷新令牌模式
  3. authorization-patterns.md(1,062行)- 访问控制实现

    • 基于角色的访问控制(RBAC)
    • 基于属性的访问控制(ABAC)
    • 中间件保护
    • API路由保护
    • 服务器操作保护
    • 行级安全(Drizzle模式)
    • 权限系统
    • 资源所有权验证
  4. input-validation-complete.md(900行)- Zod验证一切

    • 字符串、数字、布尔值、枚举验证
    • 电子邮件、URL、电话、UUID验证
    • 文件上传验证(图像、PDF、CSV)
    • 密码强度要求
    • 信用卡验证(Luhn算法)
    • IP地址验证(v4、v6)
    • 异步验证(数据库检查)
    • 错误处理和显示
  5. sql-injection-prevention.md(741行)- Drizzle ORM安全

    • 参数化查询(总是安全的)
    • 动态查询构建
    • 原始SQL安全模式
    • LIKE查询清理
    • 数据库架构安全
    • 测试SQL注入
  6. xss-prevention.md(630行)- React/Next.js XSS保护

    • React的内置转义
    • 使用DOMPurify的dangerouslySetInnerHTML
    • URL清理
    • 内容安全策略(CSP)
    • 用户生成的内容处理
    • innerHTML安全性
  7. csrf-prevention.md(597行)- 跨站请求伪造保护

    • SameSite cookies(主要防御)
    • CSRF令牌实现
    • 双重提交cookie模式
    • 服务器操作保护
    • 来源头验证
  8. secret-management.md(547行)- 安全机密处理

    • 环境变量最佳实践
    • 机密轮换策略
    • 静态加密(AES-256-GCM)
    • 机密检测(gitleaks、trufflehog)
    • 生产机密(Vercel、AWS、Vault)
  9. rate-limiting-patterns.md(826行)- 防止API滥用

    • 内存速率限制
    • Redis基础速率限制
    • API路由保护
    • 服务器操作保护
    • 基于IP的速率限制
    • 基于用户的速率限制
    • 滑动窗口算法
    • 令牌桶算法
  10. security-checklist.md(471行)- 部署前审计(250+项)

    • 认证安全(密码、会话、JWT、MFA)
    • 授权安全(访问控制、RLS)
    • 输入验证
    • 数据安全(机密、日志、数据库)
    • 文件上传安全
    • 速率限制
    • 安全头(CSP、CORS、HSTS)
    • 错误处理
    • 依赖安全
    • 监控和日志
    • 基础设施安全
    • 合规性(GDPR、PCI DSS)

🛠️ 安全工具

  • validate-security.py(414行)- 自动化漏洞扫描器
    • 检测20+漏洞类型
    • 扫描硬编码机密(API密钥、密码、令牌)
    • 检查SQL注入模式
    • 检测XSS漏洞(dangerouslySetInnerHTML、innerHTML)
    • 查找eval()和Function()使用
    • 识别弱加密(MD5、SHA1)
    • 检测不安全的随机性
    • 检查命令注入
    • 验证路径遍历防护
    • 测试密码哈希强度
    • 审计JWT安全
    • 检查CORS配置
    • 验证cookie安全(httpOnly、secure)
    • 报告TypeScript问题(@ts-ignore、any)
    • 在CRITICAL/HIGH问题上退出错误
    • 识别XSS漏洞
    • 查找eval()和Function()使用
    • 检测弱加密(MD5、SHA1)
    • 检查命令注入
    • 验证密码哈希
    • 查找CORS配置错误
    • 检查缺少httpOnly cookies
    • 报告TypeScript问题(@ts-ignore、any类型)

🚀 快速开始

在实现任何安全敏感功能之前:

# 1. 阅读相关指南
cat owasp-top-10-complete.md
cat authentication-patterns.md

# 2. 按照模式实施

# 3. 运行安全扫描器
python validate-security.py src/

# 4. 检查安全清单
cat security-checklist.md

何时使用

OWASP Top 10安全检查

1. 注入攻击

SQL注入

// ❌ 不要:查询中的字符串拼接
const query = `SELECT * FROM users WHERE email = '${email}'`
// 易受攻击:email = "' OR '1'='1"

// ✅ 做:使用Prisma(参数化查询)
const user = await prisma.user.findUnique({
  where: { email },
})

命令注入

// ❌ 不要:未经验证的shell命令
const fileName = req.body.fileName
exec(`cat ${fileName}`) // 易受攻击:fileName = "; rm -rf /"

// ✅ 做:验证输入并使用安全API
const allowedFiles = ['log.txt', 'data.csv']
if (!allowedFiles.includes(fileName)) {
  throw new Error('Invalid file name')
}
const content = await fs.readFile(path.join(SAFE_DIR, fileName))

NoSQL注入

// ❌ 不要:直接对象插入
const user = await db.users.findOne({ email: req.body.email })
// 易受攻击:{ email: { $ne: null } }

// ✅ 做:使用Zod验证输入
const emailSchema = z.string().email()
const email = emailSchema.parse(req.body.email)
const user = await db.users.findOne({ email })

2. 认证失败

密码存储

// ❌ 不要:明文密码
const user = await prisma.user.create({
  data: {
    email,
    password, // 永远不要存储明文!
  },
})

// ✅ 做:使用bcrypt哈希
import bcrypt from 'bcrypt'

const hashedPassword = await bcrypt.hash(password, 12) // 12轮以上
const user = await prisma.user.create({
  data: {
    email,
    password: hashedPassword,
  },
})

会话管理

// ❌ 不要:弱会话令牌
const sessionId = Math.random().toString()

// ✅ 做:使用加密令牌
import crypto from 'crypto'
const sessionId = crypto.randomBytes(32).toString('hex')

// ✅ 做:设置安全的会话cookie
res.setHeader('Set-Cookie', [
  `session=${sessionToken}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`,
])

JWT安全

// ❌ 不要:弱密钥
const token = jwt.sign(payload, 'secret123')

// ✅ 做:从环境变量中使用强密钥
const token = jwt.sign(payload, process.env.JWT_SECRET!, {
  expiresIn: '1h',
  algorithm: 'HS256',
})

// ✅ 做:正确验证JWT
try {
  const decoded = jwt.verify(token, process.env.JWT_SECRET!)
  // 使用解码后的数据
} catch (error) {
  throw new Error('Invalid token')
}

3. 敏感数据暴露

环境变量

// ❌ 不要:硬编码机密
const apiKey = 'sk_live_abc123def456'
const dbPassword = 'mypassword123'

// ✅ 做:环境变量
const apiKey = process.env.STRIPE_API_KEY
const dbPassword = process.env.DATABASE_PASSWORD

if (!apiKey || !dbPassword) {
  throw new Error('Missing required environment variables')
}

日志中的数据

// ❌ 不要:记录敏感数据
console.log('User data:', { email, password, creditCard })

// ✅ 做:脱敏敏感字段
const safeUserData = {
  email,
  creditCard: creditCard.slice(-4).padStart(creditCard.length, '*'),
}
console.log('User data:', safeUserData)

永远不要返回敏感数据

// ❌ 不要:在API中返回密码
const user = await prisma.user.findUnique({ where: { id } })
return user // 包括密码哈希!

// ✅ 做:排除敏感字段
const user = await prisma.user.findUnique({
  where: { id },
  select: {
    id: true,
    email: true,
    name: true,
    // 排除密码字段
  },
})
return user

4. XML外部实体(XXE)

// ❌ 不要:解析不受信任的XML
const doc = xmlParser.parse(userInput)

// ✅ 做:禁用外部实体
const parser = new xml2js.Parser({
  explicitChildren: false,
  explicitRoot: false,
  ignoreAttrs: true,
  xmlns: false,
})

5. 访问控制破损

授权检查

// ❌ 不要:缺少授权
export async function DELETE(
  request: Request,
  { params }: { params: { id: string } }
) {
  await prisma.project.delete({ where: { id: params.id } })
  return new Response(null, { status: 204 })
}

// ✅ 做:验证所有权
export async function DELETE(
  request: Request,
  { params }: { params: { id: string } }
) {
  const user = await getAuthUser(request)
  if (!user) {
    return new Response('Unauthorized', { status: 401 })
  }

  const project = await prisma.project.findUnique({
    where: { id: params.id },
  })

  if (!project) {
    return new Response('Not found', { status: 404 })
  }

  if (project.userId !== user.id) {
    return new Response('Forbidden', { status: 403 })
  }

  await prisma.project.delete({ where: { id: params.id } })
  return new Response(null, { status: 204 })
}

IDOR(不安全的直接对象引用)

// ❌ 不要:信任用户输入的ID
const userId = req.query.userId
const data = await getPrivateData(userId) // 任何用户都可以访问任何数据!

// ✅ 做:使用经过身份验证的用户ID
const userId = req.user.id // 来自经过身份验证的会话
const data = await getPrivateData(userId)

6. 安全配置错误

CORS

// ❌ 不要:允许所有来源
res.setHeader('Access-Control-Allow-Origin', '*')

// ✅ 做:白名单特定来源
const allowedOrigins = [
  'https://app.quetrex.com',
  'https://staging.quetrex.com',
]

const origin = req.headers.get('origin')
if (origin && allowedOrigins.includes(origin)) {
  res.setHeader('Access-Control-Allow-Origin', origin)
}

错误消息

// ❌ 不要:暴露内部细节
catch (error) {
  res.status(500).json({
    error: error.message, // 可能会泄露堆栈跟踪、数据库结构等。
  })
}

// ✅ 做:通用错误消息
catch (error) {
  console.error('Internal error:', error) // 内部记录
  res.status(500).json({
    error: 'An internal error occurred',
  })
}

7. 跨站脚本(XSS)

dangerouslySetInnerHTML

// ❌ 不要:未经消毒的HTML
<div dangerouslySetInnerHTML={{ __html: userInput }} />
// 易受攻击:userInput = "<script>alert('XSS')</script>"

// ✅ 做:用DOMPurify消毒
import DOMPurify from 'dompurify'

const sanitized = DOMPurify.sanitize(userInput)
<div dangerouslySetInnerHTML={{ __html: sanitized }} />

// ✅ 更好:避免使用dangerouslySetInnerHTML
<div>{userInput}</div> // React默认转义

URL处理

// ❌ 不要:未经消毒的URL
<a href={userInput}>Click here</a>
// 易受攻击:userInput = "javascript:alert('XSS')"

// ✅ 做:验证URL
function isSafeUrl(url: string): boolean {
  try {
    const parsed = new URL(url)
    return ['http:', 'https:'].includes(parsed.protocol)
  } catch {
    return false
  }
}

const href = isSafeUrl(userInput) ? userInput : '#'
<a href={href}>Click here</a>

8. 不安全的反序列化

// ❌ 不要:eval()或Function()
const code = req.body.code
eval(code) // 永远不要这样做

// ❌ 不要:未经验证的JSON
const data = JSON.parse(userInput)
// 未经验证直接使用数据

// ✅ 做:用Zod验证
const data = JSON.parse(userInput)
const validated = dataSchema.parse(data) // 验证结构和类型

9. 使用已知漏洞的组件

# ✅ 做:定期依赖审计
npm audit --audit-level=high

# ✅ 做:保持依赖更新
npm update

# ✅ 做:使用自动化工具
npm install -g snyk
snyk test

10. 记录和监控不足

// ❌ 不要:无日志
export async function POST(request: Request) {
  const user = await createUser(data)
  return Response.json(user)
}

// ✅ 做:记录安全事件
export async function POST(request: Request) {
  try {
    const user = await createUser(data)
    logger.info('User created', {
      userId: user.id,
      email: user.email,
      ip: request.headers.get('x-forwarded-for'),
      timestamp: new Date().toISOString(),
    })
    return Response.json(user)
  } catch (error) {
    logger.error('User creation failed', {
      error: error.message,
      email: data.email,
      ip: request.headers.get('x-forwarded-for'),
      timestamp: new Date().toISOString(),
    })
    throw error
  }
}

输入验证清单

// ✅ 完整的输入验证示例
import { z } from 'zod'

const createUserSchema = z.object({
  email: z.string().email().max(255),
  password: z
    .string()
    .min(8, 'Password must be at least 8 characters')
    .max(128)
    .regex(/[A-Z]/, 'Password must contain uppercase letter')
    .regex(/[a-z]/, 'Password must contain lowercase letter')
    .regex(/[0-9]/, 'Password must contain number')
    .regex(/[^A-Za-z0-9]/, 'Password must contain special character'),
  name: z.string().min(1).max(100).optional(),
})

export async function POST(request: Request) {
  // 1. 解析和验证输入
  const body = await request.json()
  const validated = createUserSchema.parse(body) // 在验证错误时抛出

  // 2. 额外的业务逻辑验证
  const existing = await prisma.user.findUnique({
    where: { email: validated.email },
  })
  if (existing) {
    throw new Error('Email already exists')
  }

  // 3. 哈希密码
  const hashedPassword = await bcrypt.hash(validated.password, 12)

  // 4. 创建用户
  const user = await prisma.user.create({
    data: {
      email: validated.email,
      password: hashedPassword,
      name: validated.name,
    },
    select: {
      id: true,
      email: true,
      name: true,
      // 排除密码
    },
  })

  // 5. 记录安全事件
  logger.info('User registered', { userId: user.id, email: user.email })

  return Response.json(user, { status: 201 })
}

安全头

// ✅ 设置安全头
export function middleware(request: NextRequest) {
  const response = NextResponse.next()

  response.headers.set('X-Content-Type-Options', 'nosniff')
  response.headers.set('X-Frame-Options', 'DENY')
  response.headers.set('X-XSS-Protection', '1; mode=block')
  response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
  response.headers.set(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline';"
  )
  response.headers.set(
    'Strict-Transport-Security',
    'max-age=31536000; includeSubDomains'
  )

  return response
}

安全审查清单

对于每次代码更改,请验证:

  • [ ] 所有用户输入都使用Zod验证
  • [ ] 没有硬编码机密(使用环境变量)
  • [ ] SQL查询参数化(使用Prisma)
  • [ ] 使用bcrypt哈希密码(12+轮)
  • [ ] JWT令牌使用强密钥并过期
  • [ ] 所有受保护路由上的授权检查
  • [ ] 没有未经DOMPurify的dangerouslySetInnerHTML
  • [ ] 没有eval()或Function()与用户输入
  • [ ] 为特定来源配置CORS
  • [ ] 错误消息不泄露内部细节
  • [ ] 安全头设置正确
  • [ ] 从API响应中排除敏感数据
  • [ ] 安全事件已记录
  • [ ] 审计依赖项(npm audit)
  • [ ] 在生产中强制执行HTTPS