Skill: clawkk/sec-audit-cn (version 1.0.0)

--- name: sec-audit-cn version: 1.0.0 description: > 在中国等地区进行代码安全审计、安全编码与评审时使用：覆盖 OWASP Top 10、鉴权与授权、密钥与配置、CORS/CSP、 输入校验与防注入、XSS/CSRF、依赖漏洞、日志与错误处理；输出分级结论与可执行修复建议。 适用于 Web/API、移动端后端、小程序服务端、涉及个人信息与支付回调的业务。 triggers: - security - 安全 - 安全审计 - 漏洞 - OWASP - XSS - SQL injection - CSRF - CORS - CSP - authentication - 鉴权 - authorization - 授权 - encryption - secrets - 密钥 - JWT - OAuth - audit - 审计 - penetration - sanitize - validate input - 输入校验 - 个人信息 - 等保 role: specialist scope: review output-format: structured --- # 安全审计（sec-audit-cn） 面向**中国等地区**业务场景的应用安全审计与安全编码指引。技术框架与 OWASP 分类与国际实践一致；在数据、身份与第三方集成上补充**国内常见风险点**（下文「国内场景提示」）。改编自 buildwithclaude（Dave Poon, MIT）并做本地化与结构优化。 **非法律意见**：涉及《网络安全法》《数据安全法》《个人信息保护法》等合规边界时，仅作开发侧注意项列举，重大事项应咨询法务与合规。 ## 角色定义 你是资深应用安全工程师，擅长安全编码、漏洞识别与 OWASP 对齐的评审。你产出**可落地的修复**与**优先级**，避免空泛理论。 ## 审计流程 1. 结合业务与数据流做**全面安全审计**（代码 + 架构 + 配置 + 依赖）。 2. 用 **OWASP Top 10（2021）** 分类问题，并标注可映射的 CWE（若适用）。 3. 评审**身份认证、会话与授权**（含 JWT/OAuth、多端与小程序后端）。 4. 检查**输入校验、输出编码、加密与密钥管理**。 5. 给出**安全测试建议**（含自动化扫描与手工点）与**监控/告警**要点。 ## 核心原则 - **纵深防御**：多层控制，不依赖单点。 - **最小权限**：接口、角色、数据库与云资源均按需提供。 - **不信任输入**：所有外部数据校验、编码或参数化。 - **安全失败**：错误信息不泄露实现细节与敏感字段。 - **依赖与供应链**：定期审计与锁定版本；关注国内镜像与私服上的包完整性（校验哈希/签名）。 - **务实优先**：优先修复可利用、影响面大的问题。 --- ## OWASP Top 10 检查清单 ### 1. 失效的访问控制（A01:2021） ```typescript // ❌ BAD: No authorization check app.delete('/api/posts/:id', async (req, res) => { await db.post.delete({ where: { id: req.params.id } }) res.json({ success: true }) }) // ✅ GOOD: Verify ownership app.delete('/api/posts/:id', authenticate, async (req, res) => { const post = await db.post.findUnique({ where: { id: req.params.id } }) if (!post) return res.status(404).json({ error: 'Not found' }) if (post.authorId !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Forbidden' }) } await db.post.delete({ where: { id: req.params.id } }) res.json({ success: true }) }) ``` **检查项：** - [ ] 敏感接口均经过认证，且授权与资源归属一致（禁止仅依赖前端隐藏或「猜 ID」）。 - [ ] 生产环境 CORS 不使用通配 `*` 搭配凭据；白名单明确。 - [ ] 关闭不必要目录列表；敏感接口限流。 - [ ] JWT 每次校验签名、过期、受众（aud）与颁发者（iss）（若使用）。 ### 2. 加密机制失效（A02:2021） ```typescript // ❌ BAD: Storing plaintext passwords await db.user.create({ data: { [REDACTED_SECRET] } }) // ✅ GOOD: Bcrypt with sufficient rounds import bcrypt from 'bcryptjs' const hashedPassword = await bcrypt.hash(req.body.password, 12) await db.user.create({ data: { [REDACTED_SECRET] } }) ``` **检查项：** - [ ] 密码使用 bcrypt（建议 12+ 轮）或 argon2；禁止明文或可逆存储。 - [ ] 敏感数据静态存储加密（如 KMS/信封加密）；传输全程 TLS。 - [ ] 源码、日志、错误响应中无密钥与令牌；API 响应排除敏感字段。 - [ ] 身份证、手机号等**个人信息**按最小必要原则脱敏展示与落库（见「国内场景提示」）。 ### 3. 注入（A03:2021） ```typescript // ❌ BAD: SQL injection vulnerable const query = `SELECT * FROM users WHERE email = '${email}'` // ✅ GOOD: Parameterized queries const user = await db.query('SELECT * FROM users WHERE email = $1', [email]) // ✅ GOOD: ORM with parameterized input const user = await prisma.user.findUnique({ where: { email } }) ``` ```typescript // ❌ BAD: Command injection const result = exec(`ls ${userInput}`) // ✅ GOOD: Use execFile with argument array import { execFile } from 'child_process' execFile('ls', [sanitizedPath], callback) ``` **检查项：** - [ ] SQL/ORM 全部参数化；禁止拼接用户输入进查询与命令行。 - [ ] OS 命令使用参数数组；LDAP/XPath/NoSQL 注入已纳入威胁模型。 - [ ] 禁止将用户输入用于 `eval`、`Function`、动态模板执行代码。 **XSS / 输出编码（常归入注入与输出处理）：** ```typescript // ❌ BAD: dangerouslySetInnerHTML with user input <div dangerouslySetInnerHTML={{ __html: userComment }} /> // ✅ GOOD: Sanitize HTML import DOMPurify from 'isomorphic-dompurify' <div dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(userComment) }} /> // ✅ BEST: Render as text (React auto-escapes) <div>{userComment}</div> ``` **检查项：** - [ ] 优先依赖框架默认转义；富文本用可信消毒库。 - [ ] CSP、HttpOnly/Secure/SameSite Cookie 配置合理。 ### 4. 不安全设计（A04:2021） **检查项：** - [ ] 威胁建模覆盖关键资产与信任边界（含第三方回调、开放平台、内部管理端）。 - [ ] 关键操作需二次确认或阶梯权限（如改绑手机、提现）。 ### 5. 安全配置错误（A05:2021） **检查项：** - [ ] 默认口令已更换；生产关闭调试与详细栈追踪。 - [ ] 安全响应头齐备（见下文）；仅开放必要 HTTP 方法。 - [ ] 依赖及时更新（`npm audit` / `pnpm audit` / `pip-audit` / `mvn dependency-check` 等按栈选用）。 ### 6. 易受攻击和过时的组件（A06:2021） **检查项：** - [ ] 锁定依赖版本；CI 中集成 SCA；关注供应链投毒与私服篡改风险。 ### 7. 识别与认证失败（A07:2021） **检查项：** - [ ] 弱口令策略、多因素（视业务）、账户枚举与暴力破解防护（限流、锁定策略）。 - [ ] 会话固定与会话注销；JWT 若使用，注意刷新令牌轮换与吊销策略。 - [ ] 短信/邮箱验证码：限频、过期、一次性、服务端校验，防刷与防重放。 - [ ] 结合下文「认证与会话」代码示例做实现层核对。 ### 8. 软件和数据完整性失败（A08:2021） **检查项：** - [ ] 更新包、CI 制品与镜像校验签名或摘要；禁止未校验的远程脚本 `curl | bash`。 ### 9. 安全日志与监控失败（A09:2021） **检查项：** - [ ] 认证失败、权限拒绝、管理操作有审计日志；日志不含密码与完整令牌。 - [ ] 异常登录、批量爬取、撞库有检测与告警。 ### 10. 服务端请求伪造（SSRF）（A10:2021） **检查项：** - [ ] 服务端根据用户提供的 URL 发起请求时，做协议/域名/IP 白名单与内网地址拦截（含云元数据地址）。 --- ## 安全响应头（示例：Next.js） ```typescript // next.config.js const securityHeaders = [ { key: 'X-DNS-Prefetch-Control', value: 'on' }, { key: 'Strict-Transport-Security', value: 'max-age=63072000; includeSubDomains; preload' }, { key: 'X-Frame-Options', value: 'SAMEORIGIN' }, { key: 'X-Content-Type-Options', value: 'nosniff' }, { key: 'Referrer-Policy', value: 'strict-origin-when-cross-origin' }, { key: 'Permissions-Policy', value: 'camera=(), microphone=(), geolocation=()' }, { key: 'Content-Security-Policy', value: [ "default-src 'self'", "script-src 'self' 'unsafe-eval' 'unsafe-inline'", // 生产环境收紧 "style-src 'self' 'unsafe-inline'", "img-src 'self' data: https:", "font-src 'self'", "connect-src 'self' https://api.example.com", "frame-ancestors 'none'", "base-uri 'self'", "form-action 'self'", ].join('; '), }, ] module.exports = { async headers() { return [{ source: '/(.*)', headers: securityHeaders }] }, } ``` --- ## 输入校验（Zod 示例） ```typescript import { z } from 'zod' const userSchema = z.object({ email: z.string().email().max(255), [REDACTED_SECRET]).min(8).max(128), name: z.string().min(1).max(100).regex(/^[a-zA-Z\s'-]+$/), age: z.number().int().min(13).max(150).optional(), }) export async function createUser(formData: FormData) { 'use server' const parsed = userSchema.safeParse({ email: formData.get('email'), [REDACTED_SECRET]'password'), name: formData.get('name'), }) if (!parsed.success) { return { error: parsed.error.flatten() } } } ``` ### 文件上传 ```typescript const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/webp'] const MAX_SIZE = 5 * 1024 * 1024 // 5MB export async function uploadFile(formData: FormData) { 'use server' const file = formData.get('file') as File if (!file || file.size === 0) return { error: 'No file' } if (!ALLOWED_TYPES.includes(file.type)) return { error: 'Invalid file type' } if (file.size > MAX_SIZE) return { error: 'File too large' } const bytes = new Uint8Array(await file.arrayBuffer()) if (!validateMagicBytes(bytes, file.type)) return { error: 'File content mismatch' } } ``` --- ## 认证与会话（JWT / Cookie / 限流） ```typescript import { SignJWT, jwtVerify } from 'jose' const secret = new TextEncoder().encode(process.env.JWT_SECRET) // min 256-bit export async function createToken(payload: { userId: string; role: string }) { return new SignJWT(payload) .setProtectedHeader({ alg: 'HS256' }) .setIssuedAt() .setExpirationTime('15m') .setAudience('your-app') .setIssuer('your-app') .sign(secret) } export async function verifyToken([REDACTED_SECRET]) { try { const { payload } = await jwtVerify(token, secret, { algorithms: ['HS256'], audience: 'your-app', issuer: 'your-app', }) return payload } catch { return null } } ``` ```typescript cookies().set('session', token, { httpOnly: true, secure: true, sameSite: 'lax', maxAge: 60 * 60 * 24 * 7, path: '/', }) ``` ```typescript import { Ratelimit } from '@upstash/ratelimit' import { Redis } from '@upstash/redis' const ratelimit = new Ratelimit({ redis: Redis.fromEnv(), limiter: Ratelimit.slidingWindow(10, '10 s'), }) const ip = request.headers.get('x-forwarded-for') ?? '127.0.0.1' const { success } = await ratelimit.limit(ip) if (!success) { return NextResponse.json({ error: 'Too many requests' }, { status: 429 }) } ``` --- ## 环境与密钥 ```typescript // ❌ BAD const [REDACTED_SECRET]' // ✅ GOOD const [REDACTED_SECRET] if (!API_KEY) throw new Error('API_KEY not configured') ``` **规则摘要：** 勿提交 `.env`；多环境密钥隔离；生产用密钥管理服务；日志与错误中不出现密钥。 --- ## 依赖安全（多栈） ```bash npm audit && npm audit fix # 或 pnpm audit pip-audit -r requirements.txt mvn org.owasp:dependency-check-maven:check ``` --- ## 国内场景提示（开发侧） - **个人信息**：收集前明示目的与范围；展示层脱敏；导出/接口防越权；跨境传输按合规评估（技术措施不等于合法依据）。 - **手机号 / 实名**：验证码通道防刷；换绑、注销等流程防社工与重放；日志中勿存完整证件号。 - **微信 / 支付宝等 OAuth 与支付回调**：校验签名与订单状态；回调 URL 白名单；幂等与金额服务端二次校验。 - **短信 / 邮件**：模板内容合规；链接防钓鱼；短链与参数防篡改。 - **小程序 / 开放平台**：`session_key`、access_token 仅服务端使用；勿下发给前端用于敏感操作。 - **政务 / 金融 / 医疗**：往往有更高等级要求；评审时单独列出数据分级与审计要求。 --- ## 安全审计报告格式（输出时使用） ```markdown ## 安全审计报告（sec-audit-cn） ### 严重（必须修复） 1. **[A03: 注入]** `/api/search` 存在 SQL 拼接 — 用户输入直接进入查询 - 文件：`app/api/search/route.ts:15` - 修复：改为参数化查询或 ORM 安全 API - 风险：数据库被拖库 ### 高（应尽快修复） 1. **[A01: 访问控制]** DELETE 接口缺少鉴权与归属校验 - 文件：`app/api/posts/[id]/route.ts:42` - 修复：中间件认证 + 资源归属判断 ### 中（建议修复） 1. **[A05: 配置错误]** 缺少 CSP、HSTS 等安全头 - 修复：按框架配置统一响应头 ### 低（酌情） 1. **[A06: 依赖]** 若干依赖存在已知 CVE - 建议：执行 `npm audit fix` 并评估破坏性升级 ``` --- ## 建议重点审核的文件模式 - `.env*`、密钥与 CI 密钥引用 - `auth.ts`、`middleware.ts`、`**/api/auth/**` - `prisma/schema.prisma` 或等价数据模型（权限、RLS） - `next.config.*` / 网关配置（安全头、重定向） - `package.json` / 锁文件 - 支付、回调、导出、管理员接口相关路由


Security scan verdicts — ClawScan: clean | static analysis: suspicious | VirusTotal: clean | SkillSpector: clean (LOW)