Communitygithub.com

安全审查

在添加身份验证、处理用户输入、处理密钥、创建 API 端点或实现支付/敏感功能时使用此技能。提供全面的安全清单和模式。

安全审查 是什么?

这个安全审查技能旨在帮助开发者在编码过程中遵循安全最佳实践,识别并防范常见的 web 安全漏洞。它会指导开发者处理密钥管理(确保所有密钥存储在环境变量中而非硬编码)、输入验证(使用 Zod 等库进行 schema 验证和文件上传检查)、防止 SQL 注入(使用参数化查询)、以及正确实现身份验证和授权(如 JWT 应使用 httpOnly cookie 而非 localStorage)。此外,技能还涵盖了 XSS 防护(通过 DOMPurify 消毒和 Content Security Policy 配置)、CSRF 保护、API 速率限制、敏感数据暴露防护、以及针对 Solana 区块链应用的签名验证。该技能适用于所有基于 JavaScript/TypeScript 的全栈项目,特别是使用 Next.js、Supabase、Express 等框架的平台。它提供了丰富的代码示例、验证步骤和部署前安全检查清单,确保在代码生成或审查过程中自动应用安全措施。

兼容平台~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/affaan-m/ECC/tree/main/skills/security-review

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

安全审查技能

本技能确保所有代码遵循安全最佳实践并识别潜在漏洞。

何时激活

  • 实现身份验证或授权
  • 处理用户输入或文件上传
  • 创建新的 API 端点
  • 处理密钥或凭据
  • 实现支付功能
  • 存储或传输敏感数据
  • 集成第三方 API

安全清单

1. 密钥管理

失败:切勿这样做

const apiKey = "sk-proj-xxxxx"  // 硬编码的密钥
const dbPassword = "password123" // 源代码中的密码

通过:始终这样做

const apiKey = process.env.OPENAI_API_KEY
const dbUrl = process.env.DATABASE_URL

// 验证密钥是否存在
if (!apiKey) {
  throw new Error('OPENAI_API_KEY 未配置')
}

验证步骤

  • 没有硬编码的 API 密钥、令牌或密码
  • 所有密钥存储在环境变量中
  • 确保 .env.local 在 .gitignore 中
  • Git 历史中没有密钥
  • 生产密钥存储在托管平台(Vercel, Railway)

2. 输入验证

始终验证用户输入

import { z } from 'zod'

// 定义验证 schema
const CreateUserSchema = z.object({
  email: z.string().email(),
  name: z.string().min(1).max(100),
  age: z.number().int().min(0).max(150)
})

// 在处理前进行验证
export async function createUser(input: unknown) {
  try {
    const validated = CreateUserSchema.parse(input)
    return await db.users.create(validated)
  } catch (error) {
    if (error instanceof z.ZodError) {
      return { success: false, errors: error.issues }
    }
    throw error
  }
}

文件上传验证

function validateFileUpload(file: File) {
  // 大小检查(最大 5MB)
  const maxSize = 5 * 1024 * 1024
  if (file.size > maxSize) {
    throw new Error('文件过大(最大 5MB)')
  }

  // 类型检查
  const allowedTypes = ['image/jpeg', 'image/png', 'image/gif']
  if (!allowedTypes.includes(file.type)) {
    throw new Error('文件类型无效')
  }

  // 扩展名检查
  const allowedExtensions = ['.jpg', '.jpeg', '.png', '.gif']
  const extension = file.name.toLowerCase().match(/\.[^.]+$/)?.[0]
  if (!extension || !allowedExtensions.includes(extension)) {
    throw new Error('文件扩展名无效')
  }

  return true
}

验证步骤

  • 所有用户输入使用 schema 验证
  • 文件上传受限(大小、类型、扩展名)
  • 查询中不直接使用用户输入
  • 白名单验证(非黑名单)
  • 错误消息不泄露敏感信息

3. SQL 注入防护

失败:切勿拼接 SQL

// 危险 - SQL 注入漏洞
const query = `SELECT * FROM users WHERE email = '${userEmail}'`
await db.query(query)

通过:始终使用参数化查询

// 安全 - 参数化查询
const { data } = await supabase
  .from('users')
  .select('*')
  .eq('email', userEmail)

// 或使用原生 SQL
await db.query(
  'SELECT * FROM users WHERE email = $1',
  [userEmail]
)

验证步骤

  • 所有数据库查询使用参数化查询
  • SQL 中没有字符串拼接
  • ORM/查询构建器使用正确
  • Supabase 查询已正确消毒

4. 身份验证与授权

JWT 令牌处理

// 失败:错误:localStorage(易受 XSS 攻击)
localStorage.setItem('token', token)

// 通过:正确:httpOnly cookie
res.setHeader('Set-Cookie',
  `token=${token}; HttpOnly; Secure; SameSite=Strict; Max-Age=3600`)

授权检查

export async function deleteUser(userId: string, requesterId: string) {
  // 始终先验证授权
  const requester = await db.users.findUnique({
    where: { id: requesterId }
  })

  if (requester.role !== 'admin') {
    return NextResponse.json(
      { error: '未授权' },
      { status: 403 }
    )
  }

  // 继续删除操作
  await db.users.delete({ where: { id: userId } })
}

行级安全(Supabase)

-- 对所有表启用 RLS
ALTER TABLE users ENABLE ROW LEVEL SECURITY;

-- 用户只能查看自己的数据
CREATE POLICY "Users view own data"
  ON users FOR SELECT
  USING (auth.uid() = id);

-- 用户只能更新自己的数据
CREATE POLICY "Users update own data"
  ON users FOR UPDATE
  USING (auth.uid() = id);

验证步骤

  • 令牌存储在 httpOnly cookie 中(非 localStorage)
  • 敏感操作前进行授权检查
  • Supabase 中启用行级安全
  • 实现基于角色的访问控制
  • 会话管理安全

5. XSS 防护

消毒 HTML

import DOMPurify from 'isomorphic-dompurify'

// 始终消毒用户提供的 HTML
function renderUserContent(html: string) {
  const clean = DOMPurify.sanitize(html, {
    ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'p'],
    ALLOWED_ATTR: []
  })
  return <div dangerouslySetInnerHTML={{ __html: clean }} />
}

内容安全策略

开始时严格,仅在记录备案的移除计划下放宽。不要默认使用 'unsafe-inline' 或 'unsafe-eval';它们会削弱 CSP 的大部分保护,应视为临时兼容性债务。

// next.config.js
const securityHeaders = [
  {
    key: 'Content-Security-Policy',
    value: `
      default-src 'self';
      base-uri 'self';
      object-src 'none';
      frame-ancestors 'none';
      script-src 'self';
      style-src 'self';
      img-src 'self' data: https:;
      font-src 'self';
      connect-src 'self' https://api.example.com;
    `.replace(/\s{2,}/g, ' ').trim()
  }
]

验证步骤

  • 用户提供的 HTML 已消毒
  • 配置了 CSP 标头
  • 没有未验证的动态内容渲染
  • 使用了 React 内置的 XSS 防护

6. CSRF 防护

CSRF 令牌

import { csrf } from '@/lib/csrf'

export async function POST(request: Request) {
  const token = request.headers.get('X-CSRF-Token')

  if (!csrf.verify(token)) {
    return NextResponse.json(
      { error: 'CSRF 令牌无效' },
      { status: 403 }
    )
  }

  // 处理请求
}

SameSite Cookie

res.setHeader('Set-Cookie',
  `session=${sessionId}; HttpOnly; Secure; SameSite=Strict`)

验证步骤

  • 状态变更操作使用 CSRF 令牌
  • 所有 cookie 使用 SameSite=Strict
  • 实现了双提交 cookie 模式

7. 速率限制

API 速率限制

import rateLimit from 'express-rate-limit'

const limiter = rateLimit({
  windowMs: 15 * 60 * 1000, // 15 分钟
  max: 100, // 每个窗口 100 个请求
  message: '请求过多'
})

// 应用到路由
app.use('/api/', limiter)

昂贵操作

// 对搜索进行严格的速率限制
const searchLimiter = rateLimit({
  windowMs: 60 * 1000, // 1 分钟
  max: 10, // 每分钟 10 个请求
  message: '搜索请求过多'
})

app.use('/api/search', searchLimiter)

验证步骤

  • 所有 API 端点启用速率限制
  • 对昂贵操作设置更严格的限制
  • 基于 IP 的速率限制
  • 基于用户的速率限制(已认证用户)

8. 敏感数据泄露

日志记录

// 失败:错误:记录敏感数据
console.log('用户登录:', { email, password })
console.log('支付:', { cardNumber, cvv })

// 通过:正确:脱敏敏感数据
console.log('用户登录:', { email, userId })
console.log('支付:', { last4: card.last4, userId })

错误消息

// 失败:错误:暴露内部细节
catch (error) {
  return NextResponse.json(
    { error: error.message, stack: error.stack },
    { status: 500 }
  )
}

// 通过:正确:通用错误消息
catch (error) {
  console.error('内部错误:', error)
  return NextResponse.json(
    { error: '发生错误。请重试。' },
    { status: 500 }
  )
}

验证步骤

  • 日志中不包含密码、令牌或密钥
  • 用户看到的错误消息是通用的
  • 详细错误仅在服务器日志中
  • 不向用户暴露堆栈跟踪

9. 区块链安全(Solana)

钱包验证

import { verify } from '@solana/web3.js'

async function verifyWalletOwnership(
  publicKey: string,
  signature: string,
  message: string
) {
  try {
    const isValid = verify(
      Buffer.from(message),
      Buffer.from(signature, 'base64'),
      Buffer.from(publicKey, 'base64')
    )
    return isValid
  } catch (error) {
    return false
  }
}

交易验证

async function verifyTransaction(transaction: Transaction) {
  // 验证接收方
  if (transaction.to !== expectedRecipient) {
    throw new Error('接收方无效')
  }

  // 验证金额
  if (transaction.amount > maxAmount) {
    throw new Error('金额超出限制')
  }

  // 验证用户余额充足
  const balance = await getBalance(transaction.from)
  if (balance < transaction.amount) {
    throw new Error('余额不足')
  }

  return true
}

验证步骤

  • 钱包签名已验证
  • 交易详情已验证
  • 交易前进行余额检查
  • 不进行盲签

10. 依赖项安全

定期更新

# 检查漏洞
npm audit

# 修复可自动修复的问题
npm audit fix

# 更新依赖项
npm update

# 检查过时的包
npm outdated

锁定文件

# 始终提交锁定文件
git add package-lock.json

# 在 CI/CD 中使用以确保可重复构建
npm ci  # 代替 npm install

验证步骤

  • 依赖项保持最新
  • 没有已知漏洞(npm audit 干净)
  • 锁定文件已提交
  • 在 GitHub 上启用 Dependabot
  • 定期安全更新

安全测试

自动化安全测试

// 测试身份验证
test('需要身份验证', async () => {
  const response = await fetch('/api/protected')
  expect(response.status).toBe(401)
})

// 测试授权
test('需要管理员角色', async () => {
  const response = await fetch('/api/admin', {
    headers: { Authorization: `Bearer ${userToken}` }
  })
  expect(response.status).toBe(403)
})

// 测试输入验证
test('拒绝无效输入', async () => {
  const response = await fetch('/api/users', {
    method: 'POST',
    body: JSON.stringify({ email: 'not-an-email' })
  })
  expect(response.status).toBe(400)
})

// 测试速率限制
test('执行速率限制', async () => {
  const requests = Array(101).fill(null).map(() =>
    fetch('/api/endpoint')
  )

  const responses = await Promise.all(requests)
  const tooManyRequests = responses.filter(r => r.status === 429)

  expect(tooManyRequests.length).toBeGreaterThan(0)
})

部署前安全清单

在任何生产部署之前:

  • 密钥:无硬编码密钥,全部使用环境变量
  • 输入验证:所有用户输入已验证
  • SQL 注入:所有查询参数化
  • XSS:用户内容已消毒
  • CSRF:保护已启用
  • 身份验证:令牌处理正确
  • 授权:角色检查已到位
  • 速率限制:所有端点已启用
  • HTTPS:生产环境强制执行
  • 安全标头:已配置 CSP、X-Frame-Options
  • 错误处理:错误中不包含敏感数据
  • 日志记录:不记录敏感数据
  • 依赖项:保持最新,无漏洞
  • 行级安全:在 Supabase 中已启用
  • CORS:正确配置
  • 文件上传:已验证(大小、类型)
  • 钱包签名:已验证(若涉及区块链)

资源


请记住:安全不是可选项。一个漏洞可能危及整个平台。如有疑问,宁可谨慎。

Individual skills in this repo

This repo contains 20 individual skills — each has its own dedicated page.

accessibility

Design, implement, and audit inclusive digital products using WCAG 2.2 Level AA. Use when building or auditing UI that must meet WCAG 2.2 Level AA, or when reviewing a change for keyboard, contrast, or screen-reader support.

affaan-m/content-engine

Create platform-native content systems for X, LinkedIn, TikTok, YouTube, newsletters, and repurposed multi-platform campaigns. Use when the user wants social posts, threads, scripts, content calendars, or one source asset adapted cleanly across platforms.

affaan-m/ECC

Multi-platform content distribution across X, LinkedIn, Threads, and Bluesky. Adapts content per platform using content-engine patterns. Never posts identical content cross-platform. Use when the user wants to distribute content across social platforms.

affaan-m/fal-ai-media

Unified media generation via fal.ai MCP — image, video, and audio. Covers text-to-image (Nano Banana), text/image-to-video (Seedance, Kling, Veo 3), text-to-speech (CSM-1B), and video-to-audio (ThinkSound). Use when the user wants to generate images, videos, or audio with AI.

affaan-m/manim-video

日本語翻訳:このファイルは manim-video 用の日本語翻訳が必要です

affaan-m/remotion-video-creation

Remotion のベストプラクティス - React で動画を作成する。3D、アニメーション、音声、字幕、チャート、トランジションなどをカバーするドメイン固有の29のルール。

affaan-m/video-editing

AI-assisted video editing workflows for cutting, structuring, and augmenting real footage. Covers the full pipeline from raw capture through FFmpeg, Remotion, ElevenLabs, fal.ai, and final polish in Descript or CapCut. Use when the user wants to edit video, cut footage, create vlogs, or build video content.

agent-architecture-audit

Full-stack diagnostic for agent and LLM applications. Audits the 12-layer agent stack for wrapper regression, memory pollution, tool discipline failures, hidden repair loops, and rendering corruption. Produces severity-ranked findings with code-first fixes. Essential for developers building agent applications, autonomous loops, or any LLM-powered feature. Use when an agent or LLM feature misbehaves and the failing layer is unknown, or before shipping an agent stack.

agent-eval

Head-to-head comparison of coding agents (Claude Code, Aider, Codex, etc.) on custom tasks with pass rate, cost, time, and consistency metrics. Use when choosing between coding agents, or when a change to an agent setup needs measured pass rate, cost, and time rather than an impression.

agent-harness-construction

Design and optimize AI agent action spaces, tool definitions, and observation formatting for higher completion rates. Use when defining or revising an agent

agentic-engineering

Operate as an agentic engineer using eval-first execution, decomposition, and cost-aware model routing. Use when planning or executing engineering work that agents will carry out end to end.

agentic-os

Build persistent multi-agent operating systems on Claude Code. Covers kernel architecture, specialist agents, slash commands, file-based memory, scheduled automation, and state management without external databases. Use when building a persistent multi-agent system on Claude Code with its own memory, commands, and scheduling.

agent-introspection-debugging

Structured self-debugging workflow for AI agent failures using capture, diagnosis, contained recovery, and introspection reports. Use when an agent run fails and you need a reproducible diagnosis instead of a retry.

agent-payment-x402

Add x402 payment execution to AI agents with per-task budgets, spending controls, and non-custodial wallets. Supports Base through agentwallet-sdk and X Layer through OKX Payments / OKX Agent Payments Protocol. Use when an agent must pay for something itself and needs per-task budgets, spending controls, and a non-custodial wallet.

agent-self-evaluation

Use after completing any non-trivial task. The agent self-rates its output on 5 axes — accuracy, completeness, clarity, actionability, conciseness — with concrete evidence per criterion. Produces a structured 1-5 scorecard with specific improvement suggestions.

agent-sort

Build an evidence-backed ECC install plan for a specific repo by sorting skills, commands, rules, hooks, and extras into DAILY vs LIBRARY buckets using parallel repo-aware review passes. Use when ECC should be trimmed to what a project actually needs instead of loading the full bundle.

ai-first-engineering

Engineering operating model for teams where AI agents generate a large share of implementation output. Use when setting team process, review gates, or ownership rules for a codebase largely written by agents.

ai-regression-testing

Regression testing strategies for AI-assisted development. Sandbox-mode API testing without database dependencies, automated bug-check workflows, and patterns to catch AI blind spots where the same model writes and reviews code. Use when adding regression coverage to AI-assisted code, or when the same model both wrote and reviewed a change.

android-clean-architecture

Clean Architecture patterns for Android and Kotlin Multiplatform projects — module structure, dependency rules, UseCases, Repositories, and data layer patterns. Use when structuring modules, layers, or data flow in an Android or KMP project.

angular-developer

Generates Angular code and provides architectural guidance. Trigger when creating projects, components, or services, or for best practices on reactivity (signals, linkedSignal, resource), forms, dependency injection, routing, SSR, accessibility (ARIA), animations, styling (component styles, Tailwind CSS), testing, or CLI tooling.

相关技能