mcpField
S
Security Engineer

Security Engineer

github.com/daffy0208安全38210 次安装44 周前更新
代码仓库

关于 Security Engineer

Security Engineer 是面向软件开发者的应用安全指南,按认证授权、输入校验、配置、数据保护和监控五个方面整理实践与检查清单。内容还包括常见漏洞防护和部署前审查。

主要功能

  1. 01认证与授权模式
  2. 02输入校验与净化
  3. 03安全配置与密钥管理
  4. 04数据加密与密码哈希
  5. 05限流、审计日志与监控
  6. 06部署前安全检查清单

适用场景

  1. 01设计 API 的身份验证与权限控制
  2. 02检查输入处理是否能防范注入和 XSS
  3. 03审查部署配置与敏感数据保护
  4. 04准备上线前的安全检查

安装

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

$npx skills add https://github.com/daffy0208/ai-dev-standards --skill security-engineer

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

附带文件README.mdmanifest.yaml

详细介绍

安全工程师

安全不可妥协——从第一天起就将其融入其中。

核心原则

安全是内建的,而不是事后补上的。

每项功能、每个端点、每条数据流都必须考虑安全影响。在生产环境中修复安全漏洞的成本,是在开发期间修复的 10 倍。

安全的 5 大支柱

支柱 1:身份验证与授权 🔐

身份验证: 你是谁?
授权: 你能做什么?

身份验证策略

JWT(JSON Web Tokens):

  • 适用场景: 无状态 API、移动应用、微服务
  • 方式: 使用密钥对令牌签名,并将其存储在 httpOnly Cookie 或 Authorization 请求头中
  • 安全性: 使用 RS256(而非 HS256),设置较短的有效期(访问令牌 15 分钟,刷新令牌 7 天)
// Example: Next.js API with JWT
import { SignJWT, jwtVerify } from 'jose'

const secret = new TextEncoder().encode(process.env.JWT_SECRET!)

export async function createToken(userId: string) {
  return await new SignJWT({ userId })
    .setProtectedHeader({ alg: 'HS256' })
    .setExpirationTime('15m')
    .sign(secret)
}

export async function verifyToken(token: string) {
  const { payload } = await jwtVerify(token, secret)
  return payload
}

基于会话的身份验证:

  • 适用场景: 传统 Web 应用、服务端渲染
  • 方式: 服务器在加密 Cookie 中存储会话 ID
  • 安全性: 使用 HttpOnly、Secure、SameSite=Strict Cookie

OAuth 2.0 / OIDC:

  • 适用场景: 社交登录、第三方集成
  • 方式: 使用 NextAuth.js、Passport.js 或 Auth0
  • 安全性: 验证 state 参数,移动端使用 PKCE
授权模式

RBAC(基于角色的访问控制):

// Define roles
enum Role {
  ADMIN = 'admin',
  USER = 'user',
  GUEST = 'guest'
}

// Check permissions
function requireRole(allowedRoles: Role[]) {
  return (req, res, next) => {
    if (!allowedRoles.includes(req.user.role)) {
      return res.status(403).json({ error: 'Forbidden' })
    }
    next()
  }
}

// Usage
app.delete('/api/users/:id', requireRole([Role.ADMIN]), deleteUser)

ABAC(基于属性的访问控制):

  • 粒度更细:用户创建的资源才允许其编辑
  • 示例:只有当 post.authorId === user.id 时,用户才能删除帖子

关键原则:

  • ✅ 授权前务必先验证身份
  • ✅ 默认拒绝(使用允许列表,而非拒绝列表)
  • ✅ 在服务器上检查权限,绝不信任客户端
  • ✅ 执行关键操作前重新验证权限

支柱 2:输入验证与清理 🛡️

绝不信任用户输入——验证、清理并转义所有内容。

防止 SQL 注入

❌ 错误(存在漏洞):

// DON'T DO THIS!
const query = `SELECT * FROM users WHERE email = '${userInput}'`
db.query(query) // SQL injection vulnerability!

✅ 正确(参数化查询):

// Always use parameterized queries
const query = 'SELECT * FROM users WHERE email = ?'
db.query(query, [userInput]) // Safe - parameterized

// With Prisma
const user = await prisma.user.findUnique({
  where: { email: userInput } // Safe - ORM handles it
})
防止 XSS(跨站脚本攻击)

❌ 错误(存在漏洞):

// DON'T DO THIS!
<div dangerouslySetInnerHTML={{ __html: userInput }} />

✅ 正确(已转义):

// React automatically escapes
;<div>{userInput}</div> // Safe

// If you must render HTML, sanitize first
import DOMPurify from 'isomorphic-dompurify'
;<div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userInput) }} />
使用 Zod 验证输入
import { z } from 'zod'

const UserSchema = z.object({
  email: z.string().email().max(255),
  password: z.string().min(8).max(100),
  age: z.number().int().min(13).max(120),
  website: z.string().url().optional()
})

// Validate
const result = UserSchema.safeParse(req.body)
if (!result.success) {
  return res.status(400).json({ errors: result.error.issues })
}

const validData = result.data // Type-safe!
文件上传安全
import multer from 'multer'

const upload = multer({
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB max
  },
  fileFilter: (req, file, cb) => {
    // Whitelist file types
    const allowedTypes = ['image/jpeg', 'image/png', 'image/webp']
    if (!allowedTypes.includes(file.mimetype)) {
      return cb(new Error('Invalid file type'))
    }
    cb(null, true)
  }
})

// Generate random filenames (don't trust user input)
const filename = crypto.randomUUID() + path.extname(file.originalname)

关键原则:

  • ✅ 在服务器上进行验证(绝不信任客户端验证)
  • ✅ 使用模式验证库(Zod、Yup、Joi)
  • ✅ 使用允许列表限定可接受的值,不要使用拒绝列表
  • ✅ 根据上下文转义输出(HTML、URL、JS)

支柱 3:安全配置 🔧
环境变量

绝不提交密钥:

# .env (add to .gitignore!)
DATABASE_URL="postgresql://user:pass@localhost:5432/db"
JWT_SECRET="generate-with-openssl-rand-base64-32"
OPENAI_API_KEY="sk-..."

在代码中访问:

// Validate env vars on startup
if (!process.env.JWT_SECRET) {
  throw new Error('JWT_SECRET is required')
}

const config = {
  jwtSecret: process.env.JWT_SECRET,
  databaseUrl: process.env.DATABASE_URL
}

密钥管理(生产环境):

  • AWS Secrets Manager
  • Vercel Environment Variables
  • HashiCorp Vault
  • Doppler
安全响应头
// Next.js middleware
export function middleware(request: NextRequest) {
  const response = NextResponse.next()

  // Prevent clickjacking
  response.headers.set('X-Frame-Options', 'DENY')

  // Prevent MIME sniffing
  response.headers.set('X-Content-Type-Options', 'nosniff')

  // XSS Protection
  response.headers.set('X-XSS-Protection', '1; mode=block')

  // Content Security Policy
  response.headers.set(
    'Content-Security-Policy',
    "default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline'"
  )

  // HTTPS only
  response.headers.set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains')

  return response
}
CORS 配置
// Configure CORS properly
app.use(
  cors({
    origin:
      process.env.NODE_ENV === 'production' ? 'https://yourdomain.com' : 'http://localhost:3000',
    credentials: true, // Allow cookies
    methods: ['GET', 'POST', 'PUT', 'DELETE'],
    allowedHeaders: ['Content-Type', 'Authorization']
  })
)

关键原则:

  • ✅ 所有密钥都使用环境变量
  • ✅ 为每个环境使用不同的密钥(dev、staging、prod)
  • ✅ 定期轮换密钥
  • ✅ 为所有响应设置安全响应头
  • ✅ 严格配置 CORS

支柱 4:数据保护 🔒
密码哈希

❌ 绝不以明文存储密码,也不要使用 MD5/SHA1!

✅ 使用 bcrypt 或 argon2:

import bcrypt from 'bcrypt'

// Hash password (on signup)
const saltRounds = 12
const hashedPassword = await bcrypt.hash(password, saltRounds)
await db.user.create({
  email,
  password: hashedPassword // Store hash, never plain text
})

// Verify password (on login)
const user = await db.user.findUnique({ where: { email } })
const isValid = await bcrypt.compare(password, user.password)
if (!isValid) {
  throw new Error('Invalid credentials')
}
静态数据加密

敏感数据应加密:

import crypto from 'crypto'

const algorithm = 'aes-256-gcm'
const key = Buffer.from(process.env.ENCRYPTION_KEY!, 'hex')

function encrypt(text: string) {
  const iv = crypto.randomBytes(16)
  const cipher = crypto.createCipheriv(algorithm, key, iv)
  const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()])
  const authTag = cipher.getAuthTag()
  return {
    iv: iv.toString('hex'),
    encryptedData: encrypted.toString('hex'),
    authTag: authTag.toString('hex')
  }
}

function decrypt(encrypted: any) {
  const decipher = crypto.createDecipheriv(algorithm, key, Buffer.from(encrypted.iv, 'hex'))
  decipher.setAuthTag(Buffer.from(encrypted.authTag, 'hex'))
  return decipher.update(encrypted.encryptedData, 'hex', 'utf8') + decipher.final('utf8')
}

// Encrypt sensitive fields
const ssn = encrypt(user.ssn)
await db.user.update({ where: { id }, data: { ssnEncrypted: JSON.stringify(ssn) } })
传输中加密

始终使用 HTTPS:

  • 开发环境:使用 mkcert 配置本地 HTTPS
  • 生产环境:Let's Encrypt、Cloudflare、Vercel(自动启用 HTTPS)

验证外部 API 证书:

// Don't disable SSL verification in production!
fetch(url, {
  // DON'T: agent: new https.Agent({ rejectUnauthorized: false })
})

关键原则:

  • ✅ 使用 bcrypt(12 轮以上)或 argon2 对密码进行哈希
  • ✅ 加密 PII(SSN、信用卡、健康数据)
  • ✅ 全程使用 HTTPS(通过 HSTS 响应头强制启用)
  • ✅ 加密数据库备份

支柱 5:监控与响应 📊
速率限制

防止暴力破解和 DDoS:

import rateLimit from 'express-rate-limit'

// Global rate limit
const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 minutes
  max: 100, // 100 requests per window
  message: 'Too many requests from this IP'
})
app.use(limiter)

// Stricter limit for auth endpoints
const authLimiter = rateLimit({
  windowMs: 15 * 60 * 1000,
  max: 5, // Only 5 login attempts per 15min
  skipSuccessfulRequests: true
})
app.post('/api/auth/login', authLimiter, loginHandler)
审计日志

记录所有与安全相关的事件:

async function auditLog(event: {
  userId?: string
  action: string
  resource: string
  ip: string
  userAgent: string
  success: boolean
  metadata?: any
}) {
  await db.auditLog.create({
    data: {
      ...event,
      timestamp: new Date()
    }
  })
}

// Usage
await auditLog({
  userId: user.id,
  action: 'LOGIN',
  resource: 'auth',
  ip: req.ip,
  userAgent: req.headers['user-agent'],
  success: true
})
错误处理

不要在错误信息中泄露敏感信息:

❌ 错误:

// Exposes database structure!
catch (error) {
  res.status(500).json({ error: error.message })
}

✅ 正确:

catch (error) {
  // Log full error server-side
  console.error('Error:', error)

  // Send generic message to client
  res.status(500).json({
    error: 'Internal server error',
    requestId: generateRequestId() // For support
  })
}
安全监控

集成工具:

  • Sentry: 错误跟踪、安全警报
  • Datadog: APM、异常检测
  • CloudWatch: AWS 基础设施监控
  • OWASP ZAP: 自动化安全扫描

核心原则:

  • ✅ 对所有公共端点实施速率限制
  • ✅ 记录身份验证尝试和授权失败
  • ✅ 切勿在错误信息中泄露敏感数据
  • ✅ 为可疑模式设置警报
  • ✅ 定期进行安全审计

OWASP Top 10 快速参考

#漏洞防护措施
1访问控制失效在服务端验证权限,默认拒绝
2加密失效使用 TLS,对密码进行哈希处理(bcrypt),加密 PII
3注入使用参数化查询,验证输入
4不安全设计威胁建模,制定安全要求
5安全配置错误使用安全默认设置,移除未使用的功能
6易受攻击的组件保持依赖项更新,使用 Dependabot
7身份验证与会话问题使用强密码、MFA,安全管理会话
8软件与数据完整性验证依赖项,为发布版本签名
9日志记录与监控失效记录安全事件,设置警报
10SSRF验证 URL,将允许的域名加入白名单

安全检查清单(部署前)

身份验证
  • 使用 bcrypt 对密码进行哈希处理(12 轮以上)
  • JWT 令牌使用 RS256,且有效期较短
  • 会话 Cookie 设置 HttpOnly、Secure、SameSite
  • 对登录端点实施速率限制(15 分钟内最多尝试 5 次)
  • 密码重置使用安全令牌(1 小时后过期)
授权
  • 所有路由都检查身份验证
  • 在服务端验证权限
  • 默认拒绝(白名单方式)
  • 未重新进行身份验证时,不允许执行敏感操作
输入验证
  • 使用架构(Zod)验证所有用户输入
  • SQL 查询使用参数化查询/ORM
  • 文件上传限制允许的类型和大小
  • 根据上下文对输出进行转义
配置
  • 代码或版本控制中不包含任何密钥
  • 所有配置都使用环境变量
  • 设置安全标头(CSP、HSTS、X-Frame-Options)
  • 严格配置 CORS
  • 在生产环境中强制使用 HTTPS
数据保护
  • 对静态存储的 PII 进行加密
  • 所有连接都使用 TLS/HTTPS
  • 对数据库备份进行加密
  • 安全管理密钥(Vault、AWS Secrets)
监控
  • 对安全事件进行审计日志记录
  • 配置错误跟踪(Sentry)
  • 对所有公共端点实施速率限制
  • 为登录失败尝试和 5xx 错误设置警报
依赖项
  • 所有依赖项均为最新版本
  • 已启用 Dependabot
  • 不存在已知漏洞(运行 npm audit)
  • 尽量减少依赖项(移除未使用的依赖项)

常见安全错误

错误 1:客户端授权

❌ 错误:

// Hiding UI doesn't prevent access!
{
  user.role === 'admin' && <DeleteButton />
}

✅ 正确:

// Always verify on server
app.delete('/api/users/:id', requireAdmin, deleteUser)

错误 2:信任客户端数据

❌ 错误:

// User can manipulate userId in request!
const userId = req.body.userId
await db.order.create({ data: { userId } })

✅ 正确:

// Get userId from authenticated session
const userId = req.user.id // From JWT/session
await db.order.create({ data: { userId } })

错误 3:密码要求过弱

❌ 错误:

if (password.length < 6) throw new Error('Too short')

✅ 正确:

const passwordSchema = z
  .string()
  .min(8, 'At least 8 characters')
  .regex(/[A-Z]/, 'Needs uppercase')
  .regex(/[a-z]/, 'Needs lowercase')
  .regex(/[0-9]/, 'Needs number')

错误 4:不安全的直接对象引用

❌ 错误:

// User can access any document by changing ID!
const doc = await db.document.findUnique({ where: { id: req.params.id } })
return res.json(doc)

✅ 正确:

// Verify ownership
const doc = await db.document.findFirst({
  where: {
    id: req.params.id,
    userId: req.user.id // Ensure user owns this document
  }
})
if (!doc) return res.status(404).json({ error: 'Not found' })
return res.json(doc)

特定框架指南

Next.js 安全
// middleware.ts - Protect routes
export function middleware(request: NextRequest) {
  const token = request.cookies.get('token')

  // Redirect to login if no token
  if (!token && request.nextUrl.pathname.startsWith('/dashboard')) {
    return NextResponse.redirect(new URL('/login', request.url))
  }

  return NextResponse.next()
}

export const config = {
  matcher: ['/dashboard/:path*', '/api/private/:path*']
}
Express 安全
import helmet from 'helmet'
import mongoSanitize from 'express-mongo-sanitize'

app.use(helmet()) // Security headers
app.use(express.json({ limit: '10mb' })) // Prevent large payloads
app.use(mongoSanitize()) // Prevent NoSQL injection
FastAPI 安全
from fastapi import Depends, HTTPException
from fastapi.security import HTTPBearer

security = HTTPBearer()

async def get_current_user(token: str = Depends(security)):
    try:
        payload = verify_token(token.credentials)
        return payload['user_id']
    except:
        raise HTTPException(status_code=401, detail="Invalid token")

@app.get("/protected")
async def protected_route(user_id: str = Depends(get_current_user)):
    return {"user_id": user_id}

安全测试

自动化工具
  • OWASP ZAP: Web 漏洞扫描器
  • Snyk: 依赖项漏洞扫描
  • npm audit: 检查已知漏洞
  • Lighthouse: 在 Chrome DevTools 中进行安全审计
手动测试
  1. 尝试 SQL 注入: ' OR '1'='1
  2. 尝试 XSS: <script>alert('XSS')</script>
  3. 尝试 CSRF: 从不同源提交表单
  4. 尝试路径遍历: ../../etc/passwd
  5. 尝试绕过身份验证: 不带令牌访问管理路由

何时使用此技能

在以下情况下使用 security-engineer 技能:

  • ✅ 实现身份验证/授权
  • ✅ 构建 API 端点
  • ✅ 处理敏感数据(PII、支付、健康信息)
  • ✅ 审查代码中的漏洞
  • ✅ 部署到生产环境
  • ✅ 开展安全审计

相关资源

技能:

  • api-designer - API 设计模式(与安全配合使用)
  • testing-strategist - 安全测试策略
  • deployment-advisor - 生产环境安全配置

模式:

  • /STANDARDS/architecture-patterns/authentication-patterns.md
  • /STANDARDS/best-practices/security-best-practices.md

外部资源:


安全是每个人的责任。从第一天起就将其融入其中。 🔒

评论

支持 Markdown