security-audit

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Resources

资源

scripts/
  validate-security-audit.sh
references/
  security-patterns.md
scripts/
  validate-security-audit.sh
references/
  security-patterns.md

Security Audit

安全审计

This skill guides you through performing comprehensive security audits on codebases to identify vulnerabilities, insecure patterns, and configuration issues. Use this when conducting security reviews, preparing for production deployments, or responding to security incidents.
本技能将指导你对代码库进行全面的安全审计,以识别漏洞、不安全模式和配置问题。适用于开展安全审查、准备生产部署或响应安全事件时使用。

When to Use This Skill

何时使用该技能

  • Conducting pre-deployment security reviews
  • Responding to security incidents or vulnerability reports
  • Performing periodic security audits on existing codebases
  • Validating security controls after major feature additions
  • Preparing for security compliance audits (SOC 2, ISO 27001)
  • Onboarding new team members to security standards
  • 开展部署前安全审查
  • 响应安全事件或漏洞报告
  • 对现有代码库进行定期安全审计
  • 新增主要功能后验证安全控制措施
  • 准备安全合规审计(SOC 2、ISO 27001)
  • 向新团队成员介绍安全标准

Audit Methodology

审计方法论

A systematic security audit follows these phases:
系统的安全审计遵循以下阶段:

Phase 1: Reconnaissance

阶段1:侦察

Objective: Understand the application architecture, tech stack, and attack surface.
Use precision_grep to map the codebase:
yaml
precision_grep:
  queries:
    - id: auth_patterns
      pattern: "(session|token|auth|login|password|jwt)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: api_endpoints
      pattern: "(router\\.(get|post|put|delete)|export.*GET|export.*POST)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: database_queries
      pattern: "(prisma\\.|db\\.|query\\(|execute\\()"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: env_usage
      pattern: "process\\.env\\."
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
Identify critical components:
  • Authentication flows (login, registration, password reset)
  • Authorization middleware and guards
  • API endpoints (public vs authenticated)
  • Database access patterns
  • File upload/download handlers
  • Payment processing logic
  • Admin panels or privileged operations
目标: 了解应用架构、技术栈和攻击面。
使用precision_grep映射代码库:
yaml
precision_grep:
  queries:
    - id: auth_patterns
      pattern: "(session|token|auth|login|password|jwt)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: api_endpoints
      pattern: "(router\\.(get|post|put|delete)|export.*GET|export.*POST)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: database_queries
      pattern: "(prisma\\.|db\\.|query\\(|execute\\()"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: env_usage
      pattern: "process\\.env\\."
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
识别关键组件:
  • 身份验证流程(登录、注册、密码重置)
  • 授权中间件与防护机制
  • API端点(公开 vs 需身份验证)
  • 数据库访问模式
  • 文件上传/下载处理程序
  • 支付处理逻辑
  • 管理面板或特权操作

Phase 2: Authentication Audit

阶段2:身份验证审计

Objective: Verify secure authentication implementation.
目标: 验证身份验证实现的安全性。

Check for Weak Session Management

检查会话管理薄弱点

Search for session configuration issues:
yaml
precision_grep:
  queries:
    - id: session_config
      pattern: "(session|cookie).*secure.*false|httpOnly.*false|sameSite.*(none|lax)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: jwt_secrets
      pattern: "jwt\\.sign.*secret.*[\"'][^\"']{1,20}[\"']|new.*JwtStrategy"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: standard
Common vulnerabilities:
  • Session cookies without
    httpOnly
    flag (exposes to XSS)
  • Session cookies without
    secure
    flag (allows HTTP transmission)
  • Weak JWT secrets (under 32 bytes entropy)
  • Sessions without expiration (immortal sessions)
  • No session invalidation on logout
Secure session example:
typescript
import { cookies } from 'next/headers';

export async function createSession(userId: string) {
  const sessionToken = await generateSecureToken();
  const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); // 7 days

  await db.session.create({
    data: {
      token: sessionToken,
      userId,
      expiresAt,
    },
  });

  cookies().set('session', sessionToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    expires: expiresAt,
    path: '/',
  });
}

export async function invalidateSession(sessionToken: string) {
  await db.session.delete({ where: { token: sessionToken } });
  cookies().delete('session');
}
搜索会话配置问题:
yaml
precision_grep:
  queries:
    - id: session_config
      pattern: "(session|cookie).*secure.*false|httpOnly.*false|sameSite.*(none|lax)"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: jwt_secrets
      pattern: "jwt\\.sign.*secret.*[\"'][^\"']{1,20}[\"']|new.*JwtStrategy"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: standard
常见漏洞:
  • 未设置
    httpOnly
    标志的会话Cookie(易受XSS攻击)
  • 未设置
    secure
    标志的会话Cookie(允许通过HTTP传输)
  • 弱JWT密钥(熵值不足32字节)
  • 无过期时间的会话(永久会话)
  • 登出时未失效会话
安全会话示例:
typescript
import { cookies } from 'next/headers';

export async function createSession(userId: string) {
  const sessionToken = await generateSecureToken();
  const expiresAt = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000); // 7 days

  await db.session.create({
    data: {
      token: sessionToken,
      userId,
      expiresAt,
    },
  });

  cookies().set('session', sessionToken, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'strict',
    expires: expiresAt,
    path: '/',
  });
}

export async function invalidateSession(sessionToken: string) {
  await db.session.delete({ where: { token: sessionToken } });
  cookies().delete('session');
}

Check for Password Security Issues

检查密码安全问题

Search for weak password handling:
yaml
precision_grep:
  queries:
    - id: password_storage
      pattern: "password.*=.*(req\\.body|params|query)|password.*toString|password.*text"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: password_hashing
      pattern: "(bcrypt|argon2|scrypt|pbkdf2)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: verbose
Common vulnerabilities:
  • Passwords stored in plain text
  • Weak hashing algorithms (MD5, SHA1, SHA256 without salt)
  • No password complexity requirements
  • Password hints or recovery questions
  • Passwords logged or exposed in error messages
Secure password hashing:
typescript
import { hash, verify } from '@node-rs/argon2';

export async function hashPassword(password: string): Promise<string> {
  return await hash(password, {
    memoryCost: 19456, // 19 MB
    timeCost: 2,
    outputLen: 32,
    parallelism: 1,
  });
}

export async function verifyPassword(
  hash: string,
  password: string
): Promise<boolean> {
  try {
    return await verify(hash, password);
  } catch {
    return false;
  }
}
搜索弱密码处理方式:
yaml
precision_grep:
  queries:
    - id: password_storage
      pattern: "password.*=.*(req\\.body|params|query)|password.*toString|password.*text"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: password_hashing
      pattern: "(bcrypt|argon2|scrypt|pbkdf2)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: verbose
常见漏洞:
  • 明文存储密码
  • 弱哈希算法(MD5、SHA1、无盐的SHA256)
  • 无密码复杂度要求
  • 密码提示或恢复问题
  • 密码在日志或错误信息中被记录或暴露
安全密码哈希实现:
typescript
import { hash, verify } from '@node-rs/argon2';

export async function hashPassword(password: string): Promise<string> {
  return await hash(password, {
    memoryCost: 19456, // 19 MB
    timeCost: 2,
    outputLen: 32,
    parallelism: 1,
  });
}

export async function verifyPassword(
  hash: string,
  password: string
): Promise<boolean> {
  try {
    return await verify(hash, password);
  } catch {
    return false;
  }
}

Check for MFA Implementation

检查MFA实现

Search for MFA patterns:
yaml
precision_grep:
  queries:
    - id: mfa_usage
      pattern: "(totp|authenticator|2fa|mfa|otp)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
MFA best practices:
  • TOTP (Time-based One-Time Password) using authenticator apps
  • Backup codes for account recovery
  • SMS OTP as fallback (not primary)
  • WebAuthn/FIDO2 for hardware keys
  • Rate limiting on OTP verification
搜索MFA模式:
yaml
precision_grep:
  queries:
    - id: mfa_usage
      pattern: "(totp|authenticator|2fa|mfa|otp)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
MFA最佳实践:
  • 使用认证器应用的TOTP(基于时间的一次性密码)
  • 用于账户恢复的备份码
  • 将SMS OTP作为 fallback(而非主要方式)
  • 用于硬件密钥的WebAuthn/FIDO2
  • OTP验证的速率限制

Phase 3: Authorization Audit

阶段3:授权审计

Objective: Ensure proper access controls and permission checks.
目标: 确保访问控制和权限检查的合理性。

Check for Missing Authorization Checks

检查缺失的授权检查

Identify API endpoints:
yaml
precision_grep:
  queries:
    - id: api_routes
      pattern: "export async function (GET|POST|PUT|DELETE|PATCH)"
      glob: "**/api/**/*.{ts,tsx,js,jsx}"
    - id: auth_middleware
      pattern: "(requireAuth|withAuth|authorize|checkPermission)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: locations
Manual review checklist:
  • Do all authenticated endpoints verify user identity?
  • Do endpoints check resource ownership (user can only access their own data)?
  • Are admin routes protected by role checks?
  • Is authorization checked server-side (not just client-side)?
Common vulnerabilities:
  • Insecure Direct Object Reference (IDOR):
    /api/users/123
    returns any user
  • Privilege escalation: Regular user can access admin functions
  • Missing authorization: Endpoints rely on client-side checks only
Secure authorization pattern:
typescript
import { auth } from '@/lib/auth';
import { db } from '@/lib/db';
import { NextResponse } from 'next/server';

export async function GET(
  req: Request,
  { params }: { params: { id: string } }
) {
  const session = await auth();
  
  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const post = await db.post.findUnique({
    where: { id: params.id },
    select: { id: true, title: true, content: true, authorId: true },
  });

  if (!post) {
    return NextResponse.json({ error: 'Not found' }, { status: 404 });
  }

  // Check ownership
  if (post.authorId !== session.user.id) {
    return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
  }

  return NextResponse.json(post);
}
识别API端点:
yaml
precision_grep:
  queries:
    - id: api_routes
      pattern: "export async function (GET|POST|PUT|DELETE|PATCH)"
      glob: "**/api/**/*.{ts,tsx,js,jsx}"
    - id: auth_middleware
      pattern: "(requireAuth|withAuth|authorize|checkPermission)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: locations
人工审查清单:
  • 所有需身份验证的端点是否都验证了用户身份?
  • 端点是否检查资源所有权(用户仅能访问自己的数据)?
  • 管理路由是否受角色检查保护?
  • 授权是否在服务器端检查(而非仅客户端)?
常见漏洞:
  • 不安全的直接对象引用(IDOR):
    /api/users/123
    返回任意用户数据
  • 权限提升:普通用户可访问管理员功能
  • 缺失授权:端点仅依赖客户端检查
安全授权模式:
typescript
import { auth } from '@/lib/auth';
import { db } from '@/lib/db';
import { NextResponse } from 'next/server';

export async function GET(
  req: Request,
  { params }: { params: { id: string } }
) {
  const session = await auth();
  
  if (!session) {
    return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
  }

  const post = await db.post.findUnique({
    where: { id: params.id },
    select: { id: true, title: true, content: true, authorId: true },
  });

  if (!post) {
    return NextResponse.json({ error: 'Not found' }, { status: 404 });
  }

  // 检查所有权
  if (post.authorId !== session.user.id) {
    return NextResponse.json({ error: 'Forbidden' }, { status: 403 });
  }

  return NextResponse.json(post);
}

Check for Role-Based Access Control (RBAC)

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

Search for role definitions:
yaml
precision_grep:
  queries:
    - id: role_checks
      pattern: "(role.*===|role.*includes|hasRole|checkRole|permissions)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: matches
RBAC implementation:
typescript
type Role = 'user' | 'admin' | 'moderator';

type Permission = 
  | 'posts:read'
  | 'posts:write'
  | 'posts:delete'
  | 'users:manage'
  | 'settings:admin';

const rolePermissions: Record<Role, Permission[]> = {
  user: ['posts:read', 'posts:write'],
  moderator: ['posts:read', 'posts:write', 'posts:delete'],
  admin: ['posts:read', 'posts:write', 'posts:delete', 'users:manage', 'settings:admin'],
};

export function hasPermission(role: Role, permission: Permission): boolean {
  return rolePermissions[role].includes(permission);
}

export function requirePermission(permission: Permission) {
  return async (req: Request) => {
    const session = await auth();
    
    if (!session || !hasPermission(session.user.role, permission)) {
      throw new Error('Insufficient permissions');
    }
  };
}
搜索角色定义:
yaml
precision_grep:
  queries:
    - id: role_checks
      pattern: "(role.*===|role.*includes|hasRole|checkRole|permissions)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: matches
RBAC实现:
typescript
type Role = 'user' | 'admin' | 'moderator';

type Permission = 
  | 'posts:read'
  | 'posts:write'
  | 'posts:delete'
  | 'users:manage'
  | 'settings:admin';

const rolePermissions: Record<Role, Permission[]> = {
  user: ['posts:read', 'posts:write'],
  moderator: ['posts:read', 'posts:write', 'posts:delete'],
  admin: ['posts:read', 'posts:write', 'posts:delete', 'users:manage', 'settings:admin'],
};

export function hasPermission(role: Role, permission: Permission): boolean {
  return rolePermissions[role].includes(permission);
}

export function requirePermission(permission: Permission) {
  return async (req: Request) => {
    const session = await auth();
    
    if (!session || !hasPermission(session.user.role, permission)) {
      throw new Error('Insufficient permissions');
    }
  };
}

Phase 4: Input Validation Audit

阶段4:输入验证审计

Objective: Prevent injection attacks and malicious input.
目标: 防止注入攻击和恶意输入。

Check for SQL Injection

检查SQL注入

Search for unsafe database queries:
yaml
precision_grep:
  queries:
    - id: raw_sql
      pattern: "(\\$executeRaw|\\$queryRaw|db\\.query|connection\\.query).*\\$\\{|.*`.*\\$\\{"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: string_concatenation
      pattern: "(SELECT|INSERT|UPDATE|DELETE).*\\+.*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: verbose
Common vulnerabilities:
  • String concatenation in SQL queries
  • Unsanitized user input in raw SQL
  • Dynamic table/column names from user input
Secure database queries:
typescript
// UNSAFE - SQL injection vulnerable
export async function getUserByEmail(email: string) {
  const query = `SELECT * FROM users WHERE email = '${email}'`;
  return await db.$queryRawUnsafe(query);
}

// SAFE - Parameterized query
export async function getUserByEmail(email: string) {
  return await db.user.findUnique({
    where: { email },
  });
}

// SAFE - Raw query with parameters
export async function searchUsers(query: string) {
  return await db.$queryRaw`
    SELECT id, name, email 
    FROM users 
    WHERE name ILIKE ${'%' + query + '%'}
    LIMIT 20
  `;
}
搜索不安全的数据库查询:
yaml
precision_grep:
  queries:
    - id: raw_sql
      pattern: "(\\$executeRaw|\\$queryRaw|db\\.query|connection\\.query).*\\$\\{|.*`.*\\$\\{"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: string_concatenation
      pattern: "(SELECT|INSERT|UPDATE|DELETE).*\\+.*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: verbose
常见漏洞:
  • SQL查询中的字符串拼接
  • 原始SQL中未经过滤的用户输入
  • 来自用户输入的动态表/列名
安全数据库查询:
typescript
// UNSAFE - 易受SQL注入攻击
export async function getUserByEmail(email: string) {
  const query = `SELECT * FROM users WHERE email = '${email}'`;
  return await db.$queryRawUnsafe(query);
}

// SAFE - 参数化查询
export async function getUserByEmail(email: string) {
  return await db.user.findUnique({
    where: { email },
  });
}

// SAFE - 带参数的原始查询
export async function searchUsers(query: string) {
  return await db.$queryRaw`
    SELECT id, name, email 
    FROM users 
    WHERE name ILIKE ${'%' + query + '%'}
    LIMIT 20
  `;
}

Check for XSS (Cross-Site Scripting)

检查XSS(跨站脚本攻击)

Search for unsafe rendering:
yaml
precision_grep:
  queries:
    - id: dangerous_html
      pattern: "(dangerouslySetInnerHTML|innerHTML|outerHTML)"
      glob: "**/*.{tsx,jsx}"
    - id: unescaped_output
      pattern: "(v-html|\\[innerHTML\\])"
      glob: "**/*.{vue,html}"
  output:
    format: locations
Common vulnerabilities:
  • Rendering unsanitized user input with
    dangerouslySetInnerHTML
  • Using
    innerHTML
    to insert user-provided content
  • Disabling auto-escaping in template engines
Secure rendering:
typescript
import DOMPurify from 'isomorphic-dompurify';

// UNSAFE - XSS vulnerable
export function UnsafeComment({ content }: { content: string }) {
  return <div dangerouslySetInnerHTML={{ __html: content }} />;
}

// SAFE - Auto-escaped by React
export function SafeComment({ content }: { content: string }) {
  return <div>{content}</div>;
}

// SAFE - Sanitized HTML if needed
export function SafeRichComment({ html }: { html: string }) {
  const sanitized = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'a'],
    ALLOWED_ATTR: ['href'],
  });
  return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}
搜索不安全的渲染方式:
yaml
precision_grep:
  queries:
    - id: dangerous_html
      pattern: "(dangerouslySetInnerHTML|innerHTML|outerHTML)"
      glob: "**/*.{tsx,jsx}"
    - id: unescaped_output
      pattern: "(v-html|\\[innerHTML\\])"
      glob: "**/*.{vue,html}"
  output:
    format: locations
常见漏洞:
  • 使用
    dangerouslySetInnerHTML
    渲染未过滤的用户输入
  • 使用
    innerHTML
    插入用户提供的内容
  • 在模板引擎中禁用自动转义
安全渲染方式:
typescript
import DOMPurify from 'isomorphic-dompurify';

// UNSAFE - 易受XSS攻击
export function UnsafeComment({ content }: { content: string }) {
  return <div dangerouslySetInnerHTML={{ __html: content }} />;
}

// SAFE - React自动转义
export function SafeComment({ content }: { content: string }) {
  return <div>{content}</div>;
}

// SAFE - 若需HTML则先净化
export function SafeRichComment({ html }: { html: string }) {
  const sanitized = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'a'],
    ALLOWED_ATTR: ['href'],
  });
  return <div dangerouslySetInnerHTML={{ __html: sanitized }} />;
}

Check for Command Injection

检查命令注入

Search for shell command execution:
yaml
precision_grep:
  queries:
    - id: shell_exec
      pattern: "(exec|spawn|execSync|spawnSync|execFile).*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: verbose
Common vulnerabilities:
  • User input passed directly to shell commands
  • Unsanitized file paths in file operations
Secure command execution:
typescript
import { spawn } from 'child_process';
import { z } from 'zod';

const allowedCommands = ['convert', 'resize', 'compress'] as const;
const commandSchema = z.enum(allowedCommands);

// UNSAFE - Command injection vulnerable
export async function processImage(filename: string) {
  exec(`convert ${filename} output.png`);
}

// SAFE - Validated input and array arguments
export async function processImage(command: string, filename: string) {
  const validCommand = commandSchema.parse(command);
  const sanitizedFilename = filename.replace(/[^a-zA-Z0-9._-]/g, '');
  
  return new Promise((resolve, reject) => {
    const child = spawn('imagemagick', [validCommand, sanitizedFilename, 'output.png']);
    child.on('exit', (code) => {
      if (code === 0) resolve(undefined);
      else reject(new Error('Processing failed'));
    });
  });
}
搜索shell命令执行:
yaml
precision_grep:
  queries:
    - id: shell_exec
      pattern: "(exec|spawn|execSync|spawnSync|execFile).*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: verbose
常见漏洞:
  • 用户输入直接传递给shell命令
  • 文件操作中未过滤的文件路径
安全命令执行:
typescript
import { spawn } from 'child_process';
import { z } from 'zod';

const allowedCommands = ['convert', 'resize', 'compress'] as const;
const commandSchema = z.enum(allowedCommands);

// UNSAFE - 易受命令注入攻击
export async function processImage(filename: string) {
  exec(`convert ${filename} output.png`);
}

// SAFE - 验证输入并使用数组参数
export async function processImage(command: string, filename: string) {
  const validCommand = commandSchema.parse(command);
  const sanitizedFilename = filename.replace(/[^a-zA-Z0-9._-]/g, '');
  
  return new Promise((resolve, reject) => {
    const child = spawn('imagemagick', [validCommand, sanitizedFilename, 'output.png']);
    child.on('exit', (code) => {
      if (code === 0) resolve(undefined);
      else reject(new Error('Processing failed'));
    });
  });
}

Check for Path Traversal

检查路径遍历

Search for file operations:
yaml
precision_grep:
  queries:
    - id: file_operations
      pattern: "(readFile|writeFile|unlink|stat|createReadStream).*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: locations
Common vulnerabilities:
  • User-controlled file paths without validation
  • Missing path normalization (allowing
    ../
    sequences)
Secure file handling:
typescript
import path from 'path';
import fs from 'fs/promises';

const UPLOADS_DIR = path.join(process.cwd(), 'uploads');

// UNSAFE - Path traversal vulnerable
export async function getFile(filename: string) {
  return await fs.readFile(`./uploads/${filename}`);
}

// SAFE - Path validation with defense against encoded traversals
export async function getFile(filename: string) {
  // Decode URL-encoded sequences (e.g., %2e%2e%2f -> ../)
  const decoded = decodeURIComponent(filename);
  const safePath = path.normalize(decoded).replace(/^(\.\.\/)+/, '');
  const fullPath = path.resolve(path.join(UPLOADS_DIR, safePath));
  
  // Ensure resolved path is within UPLOADS_DIR (prevents prefix collision)
  if (!fullPath.startsWith(UPLOADS_DIR + path.sep) && fullPath !== UPLOADS_DIR) {
    throw new Error('Invalid file path');
  }
  
  return await fs.readFile(fullPath);
}
搜索文件操作:
yaml
precision_grep:
  queries:
    - id: file_operations
      pattern: "(readFile|writeFile|unlink|stat|createReadStream).*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: locations
常见漏洞:
  • 用户可控的文件路径未验证
  • 缺失路径规范化(允许
    ../
    序列)
安全文件处理:
typescript
import path from 'path';
import fs from 'fs/promises';

const UPLOADS_DIR = path.join(process.cwd(), 'uploads');

// UNSAFE - 易受路径遍历攻击
export async function getFile(filename: string) {
  return await fs.readFile(`./uploads/${filename}`);
}

// SAFE - 路径验证并防御编码后的遍历
export async function getFile(filename: string) {
  // 解码URL编码的序列(如%2e%2e%2f -> ../)
  const decoded = decodeURIComponent(filename);
  const safePath = path.normalize(decoded).replace(/^(\.\.\/)+/, '');
  const fullPath = path.resolve(path.join(UPLOADS_DIR, safePath));
  
  // 确保解析后的路径在UPLOADS_DIR内(防止前缀冲突)
  if (!fullPath.startsWith(UPLOADS_DIR + path.sep) && fullPath !== UPLOADS_DIR) {
    throw new Error('Invalid file path');
  }
  
  return await fs.readFile(fullPath);
}

Phase 5: Data Protection Audit

阶段5:数据保护审计

Objective: Ensure sensitive data is encrypted and properly handled.
目标: 确保敏感数据被加密并妥善处理。

Check for Encryption at Rest

检查静态数据加密

Search for sensitive data storage:
yaml
precision_grep:
  queries:
    - id: sensitive_fields
      pattern: "(ssn|credit.*card|bank.*account|passport|drivers.*license)"
      glob: "**/*.{ts,tsx,js,jsx,prisma}"
    - id: encryption_usage
      pattern: "(encrypt|decrypt|cipher|crypto)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
Encryption best practices:
  • Use AES-256-GCM for symmetric encryption
  • Store encryption keys in secure key management (AWS KMS, HashiCorp Vault)
  • Never commit encryption keys to version control
  • Rotate encryption keys periodically
Secure encryption implementation:
typescript
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';

const ALGORITHM = 'aes-256-gcm';
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY;
if (!ENCRYPTION_KEY) throw new Error('ENCRYPTION_KEY environment variable is required');
const KEY = Buffer.from(ENCRYPTION_KEY, 'hex'); // 32 bytes

export function encrypt(plaintext: string): string {
  const iv = randomBytes(16);
  const cipher = createCipheriv(ALGORITHM, KEY, iv);
  
  let encrypted = cipher.update(plaintext, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  
  const authTag = cipher.getAuthTag();
  
  // Return: iv:authTag:ciphertext
  return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
}

export function decrypt(ciphertext: string): string {
  const [ivHex, authTagHex, encrypted] = ciphertext.split(':');
  
  const iv = Buffer.from(ivHex, 'hex');
  const authTag = Buffer.from(authTagHex, 'hex');
  
  const decipher = createDecipheriv(ALGORITHM, KEY, iv);
  decipher.setAuthTag(authTag);
  
  let decrypted = decipher.update(encrypted, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  
  return decrypted;
}
搜索敏感数据存储:
yaml
precision_grep:
  queries:
    - id: sensitive_fields
      pattern: "(ssn|credit.*card|bank.*account|passport|drivers.*license)"
      glob: "**/*.{ts,tsx,js,jsx,prisma}"
    - id: encryption_usage
      pattern: "(encrypt|decrypt|cipher|crypto)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
加密最佳实践:
  • 使用AES-256-GCM进行对称加密
  • 将加密密钥存储在安全的密钥管理系统中(AWS KMS、HashiCorp Vault)
  • 切勿将加密密钥提交到版本控制
  • 定期轮换加密密钥
安全加密实现:
typescript
import { createCipheriv, createDecipheriv, randomBytes } from 'crypto';

const ALGORITHM = 'aes-256-gcm';
const ENCRYPTION_KEY = process.env.ENCRYPTION_KEY;
if (!ENCRYPTION_KEY) throw new Error('ENCRYPTION_KEY environment variable is required');
const KEY = Buffer.from(ENCRYPTION_KEY, 'hex'); // 32 bytes

export function encrypt(plaintext: string): string {
  const iv = randomBytes(16);
  const cipher = createCipheriv(ALGORITHM, KEY, iv);
  
  let encrypted = cipher.update(plaintext, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  
  const authTag = cipher.getAuthTag();
  
  // 返回: iv:authTag:ciphertext
  return `${iv.toString('hex')}:${authTag.toString('hex')}:${encrypted}`;
}

export function decrypt(ciphertext: string): string {
  const [ivHex, authTagHex, encrypted] = ciphertext.split(':');
  
  const iv = Buffer.from(ivHex, 'hex');
  const authTag = Buffer.from(authTagHex, 'hex');
  
  const decipher = createDecipheriv(ALGORITHM, KEY, iv);
  decipher.setAuthTag(authTag);
  
  let decrypted = decipher.update(encrypted, 'hex', 'utf8');
  decrypted += decipher.final('utf8');
  
  return decrypted;
}

Check for PII Handling

检查PII处理

Search for personally identifiable information:
yaml
precision_grep:
  queries:
    - id: pii_fields
      pattern: "(email|phone|address|name|dob|birth.*date)"
      glob: "**/*.prisma"
    - id: logging_pii
      pattern: "(console\\.log|logger\\.(info|debug|warn)).*\\.(email|phone|ssn)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: locations
PII protection checklist:
  • Minimize PII collection (only collect what's necessary)
  • Redact PII in logs and error messages
  • Implement data retention policies (auto-delete old data)
  • Provide user data export (GDPR/CCPA compliance)
  • Provide user data deletion (right to be forgotten)
搜索个人可识别信息:
yaml
precision_grep:
  queries:
    - id: pii_fields
      pattern: "(email|phone|address|name|dob|birth.*date)"
      glob: "**/*.prisma"
    - id: logging_pii
      pattern: "(console\\.log|logger\\.(info|debug|warn)).*\\.(email|phone|ssn)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: locations
PII保护清单:
  • 最小化PII收集(仅收集必要信息)
  • 在日志和错误信息中编辑PII
  • 实施数据保留策略(自动删除旧数据)
  • 提供用户数据导出(GDPR/CCPA合规)
  • 提供用户数据删除(被遗忘权)

Check for Secrets Management

检查密钥管理

Search for hardcoded secrets:
yaml
precision_grep:
  queries:
    - id: hardcoded_secrets
      pattern: "(api.*key.*=.*[\"'][a-zA-Z0-9]{20,}|secret.*=.*[\"'][a-zA-Z0-9]{20,}|password.*=.*[\"'][^\"']{8,})"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: committed_env
      pattern: ".*"
      glob: ".env"
  output:
    format: verbose
Common vulnerabilities:
  • API keys hardcoded in source code
  • .env
    files committed to version control
  • Secrets exposed in client-side code
  • Default credentials not changed
Secure secrets management:
typescript
import { z } from 'zod';

const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  NEXTAUTH_SECRET: z.string().min(32),
  STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
  OPENAI_API_KEY: z.string().startsWith('sk-'),
});

export const env = envSchema.parse({
  DATABASE_URL: process.env.DATABASE_URL,
  NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
  STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
  OPENAI_API_KEY: process.env.OPENAI_API_KEY,
});

// Ensure .env is in .gitignore
// Use .env.example (without values) to document required variables
// Use secrets management in production (Vercel Env Vars, AWS Secrets Manager)
搜索硬编码密钥:
yaml
precision_grep:
  queries:
    - id: hardcoded_secrets
      pattern: "(api.*key.*=.*[\"'][a-zA-Z0-9]{20,}|secret.*=.*[\"'][a-zA-Z0-9]{20,}|password.*=.*[\"'][^\"']{8,})"
      glob: "**/*.{ts,tsx,js,jsx}"
    - id: committed_env
      pattern: ".*"
      glob: ".env"
  output:
    format: verbose
常见漏洞:
  • API密钥硬编码在源代码中
  • .env
    文件提交到版本控制
  • 密钥在客户端代码中暴露
  • 默认凭证未更改
安全密钥管理:
typescript
import { z } from 'zod';

const envSchema = z.object({
  DATABASE_URL: z.string().url(),
  NEXTAUTH_SECRET: z.string().min(32),
  STRIPE_SECRET_KEY: z.string().startsWith('sk_'),
  OPENAI_API_KEY: z.string().startsWith('sk-'),
});

export const env = envSchema.parse({
  DATABASE_URL: process.env.DATABASE_URL,
  NEXTAUTH_SECRET: process.env.NEXTAUTH_SECRET,
  STRIPE_SECRET_KEY: process.env.STRIPE_SECRET_KEY,
  OPENAI_API_KEY: process.env.OPENAI_API_KEY,
});

// 确保.env在.gitignore中
// 使用.env.example(不含值)记录所需变量
// 在生产环境中使用密钥管理系统(Vercel Env Vars、AWS Secrets Manager)

Phase 6: Dependency Audit

阶段6:依赖项审计

Objective: Identify and remediate vulnerable dependencies.
目标: 识别并修复易受攻击的依赖项。

Run Automated Vulnerability Scanners

运行自动化漏洞扫描器

Use npm audit:
yaml
precision_exec:
  commands:
    - cmd: "npm audit --json"
      timeout_ms: 30000
  verbosity: standard
Check for outdated packages:
yaml
precision_exec:
  commands:
    - cmd: "npm outdated --json"
      timeout_ms: 10000
  verbosity: minimal
Prioritize fixes:
  • Critical/High: Fix immediately before deployment
  • Moderate: Fix within 30 days
  • Low: Fix during regular maintenance
使用npm audit:
yaml
precision_exec:
  commands:
    - cmd: "npm audit --json"
      timeout_ms: 30000
  verbosity: standard
检查过时包:
yaml
precision_exec:
  commands:
    - cmd: "npm outdated --json"
      timeout_ms: 10000
  verbosity: minimal
优先修复:
  • 严重/高风险: 部署前立即修复
  • 中风险: 30天内修复
  • 低风险: 常规维护时修复

Check for Supply Chain Attacks

检查供应链攻击

Verify lockfile integrity:
yaml
precision_exec:
  commands:
    - cmd: "npm audit signatures"
      timeout_ms: 30000
  verbosity: standard
Checklist:
  • Commit lockfiles (
    package-lock.json
    ,
    yarn.lock
    ,
    pnpm-lock.yaml
    )
  • Review dependency changes in PRs
  • Use
    npm ci
    in CI/CD (not
    npm install
    )
  • Pin dependency versions in critical projects
  • Use tools like Socket.dev for dependency analysis
验证锁文件完整性:
yaml
precision_exec:
  commands:
    - cmd: "npm audit signatures"
      timeout_ms: 30000
  verbosity: standard
检查清单:
  • 提交锁文件(
    package-lock.json
    yarn.lock
    pnpm-lock.yaml
  • 审查PR中的依赖项变更
  • 在CI/CD中使用
    npm ci
    (而非
    npm install
  • 在关键项目中固定依赖项版本
  • 使用Socket.dev等工具进行依赖项分析

Phase 7: API Security Audit

阶段7:API安全审计

Objective: Secure API endpoints against common attacks.
目标: 保护API端点免受常见攻击。

Check for Rate Limiting

检查速率限制

Search for rate limiting implementation:
yaml
precision_grep:
  queries:
    - id: rate_limit_usage
      pattern: "(rateLimit|rate.*limiter|Ratelimit|upstash.*ratelimit)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
Implement rate limiting:
typescript
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
import { NextResponse } from 'next/server';

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
  analytics: true,
});

export async function POST(req: Request) {
  const ip = req.headers.get('x-forwarded-for') ?? 'unknown';
  const { success, limit, reset, remaining } = await ratelimit.limit(ip);

  if (!success) {
    return NextResponse.json(
      { error: 'Too many requests' },
      { 
        status: 429,
        headers: {
          'X-RateLimit-Limit': limit.toString(),
          'X-RateLimit-Remaining': remaining.toString(),
          'X-RateLimit-Reset': new Date(reset).toISOString(),
        },
      }
    );
  }

  // Process request
  return NextResponse.json({ success: true });
}
搜索速率限制实现:
yaml
precision_grep:
  queries:
    - id: rate_limit_usage
      pattern: "(rateLimit|rate.*limiter|Ratelimit|upstash.*ratelimit)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
实施速率限制:
typescript
import { Ratelimit } from '@upstash/ratelimit';
import { Redis } from '@upstash/redis';
import { NextResponse } from 'next/server';

const ratelimit = new Ratelimit({
  redis: Redis.fromEnv(),
  limiter: Ratelimit.slidingWindow(10, '10 s'), // 10 requests per 10 seconds
  analytics: true,
});

export async function POST(req: Request) {
  const ip = req.headers.get('x-forwarded-for') ?? 'unknown';
  const { success, limit, reset, remaining } = await ratelimit.limit(ip);

  if (!success) {
    return NextResponse.json(
      { error: 'Too many requests' },
      { 
        status: 429,
        headers: {
          'X-RateLimit-Limit': limit.toString(),
          'X-RateLimit-Remaining': remaining.toString(),
          'X-RateLimit-Reset': new Date(reset).toISOString(),
        },
      }
    );
  }

  // 处理请求
  return NextResponse.json({ success: true });
}

Check for CORS Configuration

检查CORS配置

Search for CORS setup:
yaml
precision_grep:
  queries:
    - id: cors_config
      pattern: "(Access-Control-Allow-Origin|cors\\(|corsOptions)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: matches
Common vulnerabilities:
  • Wildcard CORS (
    Access-Control-Allow-Origin: *
    ) with credentials
  • Overly permissive origin whitelist
  • Missing preflight request handling
Secure CORS configuration:
typescript
import { NextResponse } from 'next/server';

const ALLOWED_ORIGINS = [
  'https://example.com',
  'https://app.example.com',
];

export async function GET(req: Request) {
  const origin = req.headers.get('origin');
  
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
  };
  
  if (origin && ALLOWED_ORIGINS.includes(origin)) {
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
  }
  
  return NextResponse.json({ data: 'response' }, { headers });
}
搜索CORS设置:
yaml
precision_grep:
  queries:
    - id: cors_config
      pattern: "(Access-Control-Allow-Origin|cors\\(|corsOptions)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: matches
常见漏洞:
  • 带凭证的通配符CORS(
    Access-Control-Allow-Origin: *
  • 过于宽松的源白名单
  • 缺失预检请求处理
安全CORS配置:
typescript
import { NextResponse } from 'next/server';

const ALLOWED_ORIGINS = [
  'https://example.com',
  'https://app.example.com',
];

export async function GET(req: Request) {
  const origin = req.headers.get('origin');
  
  const headers: Record<string, string> = {
    'Content-Type': 'application/json',
  };
  
  if (origin && ALLOWED_ORIGINS.includes(origin)) {
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
  }
  
  return NextResponse.json({ data: 'response' }, { headers });
}

Webhook Signature Verification

Webhook签名验证

Best practice: Use
crypto.timingSafeEqual()
for comparing webhook signatures to prevent timing attacks:
typescript
import crypto from 'crypto';

export function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean {
  const expectedSignature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  const signatureBuffer = Buffer.from(signature);
  const expectedBuffer = Buffer.from(expectedSignature);
  
  // Prevent timing attacks - constant-time comparison
  if (signatureBuffer.length !== expectedBuffer.length) return false;
  return crypto.timingSafeEqual(signatureBuffer, expectedBuffer);
}
最佳实践: 使用
crypto.timingSafeEqual()
比较Webhook签名,以防止时序攻击:
typescript
import crypto from 'crypto';

export function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean {
  const expectedSignature = crypto.createHmac('sha256', secret).update(payload).digest('hex');
  const signatureBuffer = Buffer.from(signature);
  const expectedBuffer = Buffer.from(expectedSignature);
  
  // 防止时序攻击 - 恒定时间比较
  if (signatureBuffer.length !== expectedBuffer.length) return false;
  return crypto.timingSafeEqual(signatureBuffer, expectedBuffer);
}

CORS Preflight Handling

CORS预检请求处理

typescript
export async function OPTIONS(req: Request) {
  const origin = req.headers.get('origin');
  
  const headers: Record<string, string> = {
    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    'Access-Control-Max-Age': '86400', // 24 hours
  };
  
  if (origin && ALLOWED_ORIGINS.includes(origin)) {
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
  }
  
  return new NextResponse(null, { status: 204, headers });
}
typescript
export async function OPTIONS(req: Request) {
  const origin = req.headers.get('origin');
  
  const headers: Record<string, string> = {
    'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
    'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    'Access-Control-Max-Age': '86400', // 24 hours
  };
  
  if (origin && ALLOWED_ORIGINS.includes(origin)) {
    headers['Access-Control-Allow-Origin'] = origin;
    headers['Access-Control-Allow-Credentials'] = 'true';
  }
  
  return new NextResponse(null, { status: 204, headers });
}

Check for CSRF Protection

检查CSRF防护

Search for CSRF implementation:
yaml
precision_grep:
  queries:
    - id: csrf_tokens
      pattern: "(csrf|csrfToken|xsrf)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
CSRF protection strategies:
  • Use SameSite cookies (
    sameSite: 'strict'
    or
    'lax'
    )
  • Implement CSRF tokens for state-changing operations
  • Require custom headers for API requests (e.g.,
    X-Requested-With
    )
  • Verify
    Origin
    and
    Referer
    headers
搜索CSRF实现:
yaml
precision_grep:
  queries:
    - id: csrf_tokens
      pattern: "(csrf|csrfToken|xsrf)"
      glob: "**/*.{ts,tsx,js,jsx}"
  output:
    format: minimal
CSRF防护策略:
  • 使用SameSite Cookie(
    sameSite: 'strict'
    'lax'
  • 为状态变更操作实现CSRF令牌
  • API请求要求自定义头(如
    X-Requested-With
  • 验证
    Origin
    Referer

Check for Content Security Policy (CSP)

检查内容安全策略(CSP)

Search for CSP headers:
yaml
precision_grep:
  queries:
    - id: csp_headers
      pattern: "Content-Security-Policy"
      glob: "**/*.{ts,tsx,js,jsx,json}"
  output:
    format: locations
Implement CSP:
typescript
// next.config.js
const ContentSecurityPolicy = `
  default-src 'self';
  // WARNING: 'unsafe-eval' and 'unsafe-inline' significantly weaken CSP. Use nonces or hashes instead.
  script-src 'self' 'unsafe-eval' 'unsafe-inline' https://cdn.vercel-insights.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' data:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
`;

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: ContentSecurityPolicy.replace(/\n/g, ''),
          },
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff',
          },
          {
            key: 'Referrer-Policy',
            value: 'strict-origin-when-cross-origin',
          },
          {
            key: 'Permissions-Policy',
            value: 'camera=(), microphone=(), geolocation=()',
          },
        ],
      },
    ];
  },
};
搜索CSP头:
yaml
precision_grep:
  queries:
    - id: csp_headers
      pattern: "Content-Security-Policy"
      glob: "**/*.{ts,tsx,js,jsx,json}"
  output:
    format: locations
实施CSP:
typescript
// next.config.js
const ContentSecurityPolicy = `
  default-src 'self';
  // WARNING: 'unsafe-eval' and 'unsafe-inline' significantly weaken CSP. Use nonces or hashes instead.
  script-src 'self' 'unsafe-eval' 'unsafe-inline' https://cdn.vercel-insights.com;
  style-src 'self' 'unsafe-inline';
  img-src 'self' data: https:;
  font-src 'self' data:;
  connect-src 'self' https://api.example.com;
  frame-ancestors 'none';
  base-uri 'self';
  form-action 'self';
`;

module.exports = {
  async headers() {
    return [
      {
        source: '/(.*)',
        headers: [
          {
            key: 'Content-Security-Policy',
            value: ContentSecurityPolicy.replace(/\n/g, ''),
          },
          {
            key: 'X-Frame-Options',
            value: 'DENY',
          },
          {
            key: 'X-Content-Type-Options',
            value: 'nosniff',
          },
          {
            key: 'Referrer-Policy',
            value: 'strict-origin-when-cross-origin',
          },
          {
            key: 'Permissions-Policy',
            value: 'camera=(), microphone=(), geolocation=()',
          },
        ],
      },
    ];
  },
};

Phase 8: Infrastructure Security Audit

阶段8:基础设施安全审计

Objective: Harden deployment infrastructure.
目标: 加固部署基础设施。

Check Docker Security

检查Docker安全

Search for Dockerfile:
yaml
precision_read:
  files:
    - path: "Dockerfile"
      extract: content
  verbosity: minimal
Docker security checklist:
  • Use minimal base images (alpine, distroless)
  • Run as non-root user
  • Multi-stage builds to reduce attack surface
  • No secrets in image layers (use build args)
  • Pin base image versions (avoid
    latest
    tag)
  • Scan images for vulnerabilities (
    docker scan
    , Trivy)
Secure Dockerfile:
dockerfile
FROM node:20-alpine AS base

FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production
搜索Dockerfile:
yaml
precision_read:
  files:
    - path: "Dockerfile"
      extract: content
  verbosity: minimal
Docker安全检查清单:
  • 使用最小化基础镜像(alpine、distroless)
  • 以非root用户运行
  • 多阶段构建以减少攻击面
  • 镜像层中无密钥(使用构建参数)
  • 固定基础镜像版本(避免
    latest
    标签)
  • 扫描镜像漏洞(
    docker scan
    、Trivy)
安全Dockerfile示例:
dockerfile
FROM node:20-alpine AS base

FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build

FROM base AS runner
WORKDIR /app

ENV NODE_ENV=production

Create non-root user

创建非root用户

RUN addgroup --system --gid 1001 nodejs &&
adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/public ./public
USER nextjs
EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0"
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
CMD ["node", "server.js"]
undefined
RUN addgroup --system --gid 1001 nodejs &&
adduser --system --uid 1001 nextjs
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder --chown=nextjs:nodejs /app/public ./public
USER nextjs
EXPOSE 3000 ENV PORT=3000 ENV HOSTNAME="0.0.0.0"
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3
CMD node -e "require('http').get('http://localhost:3000/api/health', (r) => process.exit(r.statusCode === 200 ? 0 : 1))"
CMD ["node", "server.js"]
undefined

Check Environment Variable Security

检查环境变量安全

Search for env file usage:
yaml
precision_glob:
  patterns:
    - ".env*"
    - "*.env"
  verbosity: count_only
Verify .gitignore:
yaml
precision_read:
  files:
    - path: ".gitignore"
      extract: content
  verbosity: minimal
Environment security checklist:
  • .env
    files in
    .gitignore
  • Use
    .env.example
    (without values) to document variables
  • Use secrets management in production (not
    .env
    files)
  • Separate environments (development, staging, production)
  • Rotate secrets regularly
搜索env文件使用:
yaml
precision_glob:
  patterns:
    - ".env*"
    - "*.env"
  verbosity: count_only
验证.gitignore:
yaml
precision_read:
  files:
    - path: ".gitignore"
      extract: content
  verbosity: minimal
环境安全检查清单:
  • .env
    文件在
    .gitignore
  • 使用
    .env.example
    (不含值)记录变量
  • 生产环境使用密钥管理系统(而非
    .env
    文件)
  • 分离环境(开发、 staging、生产)
  • 定期轮换密钥

Check TLS Configuration

检查TLS配置

Verify HTTPS enforcement:
yaml
precision_grep:
  queries:
    - id: https_redirect
      pattern: "(https|ssl|tls|hsts|Strict-Transport-Security)"
      glob: "**/*.{ts,tsx,js,jsx,json}"
  output:
    format: minimal
TLS best practices:
  • Enforce HTTPS (redirect HTTP to HTTPS)
  • Enable HSTS (Strict-Transport-Security)
  • Use TLS 1.2+ (disable TLS 1.0, 1.1)
  • Use strong cipher suites
  • Implement certificate pinning for mobile apps
验证HTTPS强制:
yaml
precision_grep:
  queries:
    - id: https_redirect
      pattern: "(https|ssl|tls|hsts|Strict-Transport-Security)"
      glob: "**/*.{ts,tsx,js,jsx,json}"
  output:
    format: minimal
TLS最佳实践:
  • 强制HTTPS(将HTTP重定向到HTTPS)
  • 启用HSTS(Strict-Transport-Security)
  • 使用TLS 1.2+(禁用TLS 1.0、1.1)
  • 使用强密码套件
  • 为移动应用实现证书固定

Audit Reporting

审计报告

Structure your audit findings in this format:
按以下格式组织审计结果:

Executive Summary

执行摘要

markdown
undefined
markdown
undefined

Security Audit Report

安全审计报告

Application: [Name] Audit Date: [Date] Auditor: [Name/Team] Scope: [Components audited]
应用: [名称] 审计日期: [日期] 审计员: [名称/团队] 范围: [审计的组件]

Summary

摘要

  • Total findings: X
  • Critical: Y
  • High: Z
  • Medium: A
  • Low: B
  • 总发现数:X
  • 严重:Y
  • 高:Z
  • 中:A
  • 低:B

Risk Assessment

风险评估

[Overall risk level: Critical/High/Medium/Low]
undefined
[整体风险等级:严重/高/中/低]
undefined

Detailed Findings

详细发现

For each vulnerability:
markdown
undefined
每个漏洞的格式:
markdown
undefined

[SEVERITY] Finding #X: [Title]

[严重程度] 发现#X:[标题]

Category: [Authentication/Authorization/Input Validation/etc.] Severity: [Critical/High/Medium/Low] CWE: [CWE-XXX if applicable]
Description: [Clear description of the vulnerability]
Location:
  • File:
    path/to/file.ts
  • Lines: 42-58
Impact: [What can an attacker do? What data is at risk?]
Proof of Concept:
typescript
// Example exploit code or reproduction steps
Remediation:
typescript
// Secure code example
References:
  • [OWASP Link]
  • [CWE Link]
undefined
类别: [身份验证/授权/输入验证等] 严重程度: [严重/高/中/低] CWE: [适用的CWE-XXX]
描述: [漏洞的清晰描述]
位置:
  • 文件:
    path/to/file.ts
  • 行:42-58
影响: [攻击者可执行的操作?哪些数据面临风险?]
概念验证:
typescript
// 示例利用代码或复现步骤
修复方案:
typescript
// 安全代码示例
参考:
  • [OWASP链接]
  • [CWE链接]
undefined

Severity Classification

严重程度分类

SeverityCriteria
CriticalRemote code execution, authentication bypass, sensitive data exposure
HighPrivilege escalation, SQL injection, XSS in critical flows
MediumInformation disclosure, CSRF, weak authentication
LowMinor information leaks, missing security headers
严重程度标准
严重远程代码执行、身份验证绕过、敏感数据暴露
权限提升、SQL注入、关键流程中的XSS
信息泄露、CSRF、弱身份验证
轻微信息泄露、缺失安全头

Precision Tool Workflows

Precision工具工作流

Full Security Scan Workflow

全面安全扫描工作流

Run a comprehensive security scan using precision_grep:
yaml
precision_grep:
  queries:
    # Authentication issues
    - id: weak_auth
      pattern: "(password.*plain|password.*clear|md5|sha1)\\("
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # SQL injection
    - id: sql_injection
      pattern: "(\\$queryRaw|\\$executeRaw).*\\$\\{|query.*\\+.*params"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # XSS
    - id: xss
      pattern: "(dangerouslySetInnerHTML|innerHTML|v-html)"
      glob: "**/*.{tsx,jsx,vue}"
    
    # Command injection
    - id: command_injection
      pattern: "(exec|spawn).*\\(.*req\\.(body|query)"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # Path traversal
    - id: path_traversal
      pattern: "(readFile|writeFile).*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # Hardcoded secrets
    - id: hardcoded_secrets
      pattern: "(api.*key.*=.*[\"'][a-zA-Z0-9]{20,}|sk_live)"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # Insecure cookies
    - id: insecure_cookies
      pattern: "(httpOnly.*false|secure.*false|sameSite.*none)"
      glob: "**/*.{ts,tsx,js,jsx}"
  
  output:
    format: locations
使用precision_grep运行全面安全扫描:
yaml
precision_grep:
  queries:
    # 身份验证问题
    - id: weak_auth
      pattern: "(password.*plain|password.*clear|md5|sha1)\\("
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # SQL注入
    - id: sql_injection
      pattern: "(\\$queryRaw|\\$executeRaw).*\\$\\{|query.*\\+.*params"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # XSS
    - id: xss
      pattern: "(dangerouslySetInnerHTML|innerHTML|v-html)"
      glob: "**/*.{tsx,jsx,vue}"
    
    # 命令注入
    - id: command_injection
      pattern: "(exec|spawn).*\\(.*req\\.(body|query)"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # 路径遍历
    - id: path_traversal
      pattern: "(readFile|writeFile).*req\\.(body|query|params)"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # 硬编码密钥
    - id: hardcoded_secrets
      pattern: "(api.*key.*=.*[\"'][a-zA-Z0-9]{20,}|sk_live)"
      glob: "**/*.{ts,tsx,js,jsx}"
    
    # 不安全的Cookie
    - id: insecure_cookies
      pattern: "(httpOnly.*false|secure.*false|sameSite.*none)"
      glob: "**/*.{ts,tsx,js,jsx}"
  
  output:
    format: locations

Batch Security Audit

批量安全审计

Use discover + batch for efficient auditing:
yaml
discover:
  queries:
    - id: auth_files
      type: glob
      patterns: ["**/auth/**/*.{ts,tsx,js,jsx}", "**/api/auth/**/*.{ts,tsx,js,jsx}"]
    - id: api_routes
      type: glob
      patterns: ["**/api/**/*.{ts,tsx,js,jsx}"]
    - id: db_files
      type: grep
      pattern: "(prisma|db|database)"
      glob: "**/*.{ts,tsx,js,jsx}"
  verbosity: files_only
Then batch read and analyze:
yaml
precision_read:
  files: [/* Use discovered files */]
  extract: symbols
  symbol_filter: ["function", "class"]
  verbosity: standard
使用discover + batch进行高效审计:
yaml
discover:
  queries:
    - id: auth_files
      type: glob
      patterns: ["**/auth/**/*.{ts,tsx,js,jsx}", "**/api/auth/**/*.{ts,tsx,js,jsx}"]
    - id: api_routes
      type: glob
      patterns: ["**/api/**/*.{ts,tsx,js,jsx}"]
    - id: db_files
      type: grep
      pattern: "(prisma|db|database)"
      glob: "**/*.{ts,tsx,js,jsx}"
  verbosity: files_only
然后批量读取并分析:
yaml
precision_read:
  files: [/* 使用发现的文件 */]
  extract: symbols
  symbol_filter: ["function", "class"]
  verbosity: standard

Automated Security Testing

自动化安全测试

Integrate security checks into CI/CD:
yaml
undefined
将安全检查集成到CI/CD:
yaml
undefined

.github/workflows/security.yml

.github/workflows/security.yml

name: Security Scan
on: push: branches: [main] pull_request: branches: [main]
jobs: security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
  - name: Run npm audit
    run: npm audit --audit-level=high
  
  - name: Run Snyk security scan
    uses: snyk/actions/node@master
    env:
      SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
  
  - name: Run Trivy vulnerability scanner
    uses: aquasecurity/trivy-action@master
    with:
      scan-type: 'fs'
      scan-ref: '.'
      severity: 'CRITICAL,HIGH'
  
  - name: Run OWASP ZAP scan
    uses: zaproxy/action-baseline@v0.7.0
    with:
      target: 'http://localhost:3000'
undefined
name: Security Scan
on: push: branches: [main] pull_request: branches: [main]
jobs: security: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4
  - name: Run npm audit
    run: npm audit --audit-level=high
  
  - name: Run Snyk security scan
    uses: snyk/actions/node@master
    env:
      SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
  
  - name: Run Trivy vulnerability scanner
    uses: aquasecurity/trivy-action@master
    with:
      scan-type: 'fs'
      scan-ref: '.'
      severity: 'CRITICAL,HIGH'
  
  - name: Run OWASP ZAP scan
    uses: zaproxy/action-baseline@v0.7.0
    with:
      target: 'http://localhost:3000'
undefined

Common Security Mistakes

常见安全错误

1. Trusting Client-Side Validation

1. 信任客户端验证

Problem: Relying on client-side checks for security.
Solution: Always validate on the server.
typescript
// UNSAFE - Client-side only
export function ClientForm() {
  const [email, setEmail] = useState('');
  
  const isValid = email.includes('@');
  
  return (
    <form onSubmit={() => fetch('/api/subscribe', {
      method: 'POST',
      body: JSON.stringify({ email }),
    })}>
      <input value={email} onChange={(e) => setEmail(e.target.value)} />
      <button disabled={!isValid}>Subscribe</button>
    </form>
  );
}

// SAFE - Server-side validation
export async function POST(req: Request) {
  const body = await req.json();
  
  const schema = z.object({
    email: z.string().email(),
  });
  
  const result = schema.safeParse(body);
  
  if (!result.success) {
    return NextResponse.json(
      { error: result.error.flatten() },
      { status: 400 }
    );
  }
  
  // Process valid email
  await subscribeUser(result.data.email);
  return NextResponse.json({ success: true });
}
问题: 依赖客户端检查实现安全。
解决方案: 始终在服务器端验证。
typescript
// UNSAFE - 仅客户端验证
export function ClientForm() {
  const [email, setEmail] = useState('');
  
  const isValid = email.includes('@');
  
  return (
    <form onSubmit={() => fetch('/api/subscribe', {
      method: 'POST',
      body: JSON.stringify({ email }),
    })}>
      <input value={email} onChange={(e) => setEmail(e.target.value)} />
      <button disabled={!isValid}>Subscribe</button>
    </form>
  );
}

// SAFE - 服务器端验证
export async function POST(req: Request) {
  const body = await req.json();
  
  const schema = z.object({
    email: z.string().email(),
  });
  
  const result = schema.safeParse(body);
  
  if (!result.success) {
    return NextResponse.json(
      { error: result.error.flatten() },
      { status: 400 }
    );
  }
  
  // 处理有效邮箱
  await subscribeUser(result.data.email);
  return NextResponse.json({ success: true });
}

2. Exposing Sensitive Data in API Responses

2. API响应中暴露敏感数据

Problem: Returning more data than needed.
Solution: Use explicit
select
to limit fields.
typescript
// UNSAFE - Returns password hash
export async function GET(req: Request) {
  const user = await db.user.findUnique({ where: { id: userId } });
  return NextResponse.json(user);
}

// SAFE - Excludes sensitive fields
export async function GET(req: Request) {
  const user = await db.user.findUnique({
    where: { id: userId },
    select: {
      id: true,
      name: true,
      email: true,
      avatar: true,
      // passwordHash excluded
    },
  });
  return NextResponse.json(user);
}
问题: 返回超出需求的数据。
解决方案: 使用显式
select
限制字段。
typescript
// UNSAFE - 返回密码哈希
export async function GET(req: Request) {
  const user = await db.user.findUnique({ where: { id: userId } });
  return NextResponse.json(user);
}

// SAFE - 排除敏感字段
export async function GET(req: Request) {
  const user = await db.user.findUnique({
    where: { id: userId },
    select: {
      id: true,
      name: true,
      email: true,
      avatar: true,
      // 排除passwordHash
    },
  });
  return NextResponse.json(user);
}

3. Logging Sensitive Data

3. 记录敏感数据

Problem: Writing PII or secrets to logs.
Solution: Redact sensitive data before logging.
typescript
// UNSAFE - Logs password
export async function login(email: string, password: string) {
  console.log('Login attempt:', { email, password });
  // ...
}

// SAFE - Redacts password
export async function login(email: string, password: string) {
  console.log('Login attempt:', { email, password: '[REDACTED]' });
  // ...
}
问题: 将PII或密钥写入日志。
解决方案: 记录前编辑敏感数据。
typescript
// UNSAFE - 记录密码
export async function login(email: string, password: string) {
  console.log('Login attempt:', { email, password });
  // ...
}

// SAFE - 编辑密码
export async function login(email: string, password: string) {
  console.log('Login attempt:', { email, password: '[REDACTED]' });
  // ...
}

Post-Audit Actions

审计后操作

After completing the audit:
  1. Prioritize findings by severity and exploitability
  2. Create tickets for each finding (link to audit report)
  3. Fix critical/high issues immediately
  4. Run validation script to verify remediations
  5. Schedule follow-up audit after fixes
  6. Update security documentation with lessons learned
  7. Train team on common vulnerabilities found
完成审计后:
  1. 按严重程度和可利用性优先处理发现的问题
  2. 为每个发现创建工单(链接到审计报告)
  3. 立即修复严重/高风险问题
  4. 运行验证脚本以确认修复
  5. 修复后安排后续审计
  6. 更新安全文档并记录经验教训
  7. 培训团队了解发现的常见漏洞

Validation

验证

Run the validation script after audit remediation:
bash
./scripts/validate-security-audit.sh /path/to/project
The script checks for:
  • Common vulnerability patterns
  • Secure authentication implementation
  • Input validation coverage
  • Secrets management
  • Security headers configuration
  • Dependency vulnerabilities
审计修复后运行验证脚本:
bash
./scripts/validate-security-audit.sh /path/to/project
该脚本检查:
  • 常见漏洞模式
  • 安全身份验证实现
  • 输入验证覆盖范围
  • 密钥管理
  • 安全头配置
  • 依赖项漏洞

Further Reading

进一步阅读