Skip to Content

28f - 后端 Steering 规则与反模式

本文是《AI Agent 实战手册》第 28 章第 6 节。 上一节:28e-微服务与Serverless | 下一节:29a-AI辅助数据库设计概览

概述

Steering 规则是 AI 编码助手的”行为宪法”——它们在每次交互前注入持久化上下文,确保 AI 生成的后端代码符合安全规范、性能要求和架构约束。后端开发的安全风险远高于前端:SQL 注入可导致数据泄露、认证绕过可导致账户劫持、密钥泄露可导致整个系统被攻破。2025 年的研究表明,约 45% 的 AI 生成代码存在安全缺陷(Forrester/Cursor 研究 ,2025),而 OWASP API Security Top 10 中的大部分漏洞都可以通过精心设计的 Steering 规则预防。本节提供完整的后端 Steering 规则模板(覆盖 CLAUDE.md、Kiro Steering、Cursor Rules 三大平台)、十大后端反模式的识别与修复指南,以及用于检测和修复每种反模式的 prompt 模板。


1. 后端 Steering 规则概述

1.1 为什么后端需要专用 Steering 规则

后端开发的安全和性能要求与前端截然不同,AI 在以下方面特别容易犯错:

  1. 安全漏洞隐蔽性:SQL 注入、认证绕过等漏洞在代码层面看起来”能运行”,但存在严重安全风险
  2. 数据库交互复杂性:N+1 查询、缺少索引、事务处理不当等问题在小数据量下不明显,生产环境才暴露
  3. 密钥管理敏感性:AI 倾向于在代码中硬编码 API 密钥、数据库密码等敏感信息
  4. 并发与竞态条件:AI 生成的代码通常不考虑并发场景,导致竞态条件和数据不一致
  5. 输入验证缺失:AI 倾向于信任所有输入,缺少服务端验证和清洗
  6. 错误处理粗糙:AI 经常使用 catch-all 错误处理,泄露内部实现细节或吞掉关键错误
  7. 限流与防护缺失:AI 生成的 API 通常没有速率限制,容易被滥用或 DDoS 攻击
  8. 日志与审计不足:AI 不会主动添加安全审计日志,或在日志中泄露敏感数据

1.2 工具推荐

工具用途价格适用场景
Claude CodeAgentic 编码,CLAUDE.md 规则按 token 计费(Max $100/月起)复杂后端项目、全栈开发
KiroSpec-Driven 开发,分层 Steering免费(预览期)规范化团队开发流程
CursorAI IDE,.cursorrules 规则免费 / Pro $20/月日常后端开发
Snyk依赖漏洞扫描 + 代码安全分析免费(开源)/ Team $25/月/人CI/CD 安全门
SonarQube代码质量和安全分析免费(社区版)/ Developer $150/年起持续代码质量监控
Semgrep自定义规则的静态分析免费(开源)/ Team $40/月/人自定义安全规则检测
OWASP ZAP动态应用安全测试(DAST)免费(开源)API 安全扫描
Vault (HashiCorp)密钥管理免费(开源)/ Cloud $1.58/小时起生产密钥管理
express-rate-limit / @nestjs/throttlerAPI 限流中间件免费(开源)Node.js API 限流
Prisma / Drizzle ORM类型安全的数据库访问免费(开源)/ Prisma Accelerate 按用量防止 SQL 注入

2. 完整后端 Steering 规则模板

2.1 CLAUDE.md 后端规则模板

以下是一个适用于 Node.js/TypeScript + PostgreSQL 后端项目的完整 CLAUDE.md 规则模板:

# CLAUDE.md — 后端项目规则 ## 项目概述 - 运行时:Node.js 22 LTS + TypeScript 5.x(strict mode) - 框架:Express 5 / Fastify 5 / NestJS 11 - 数据库:PostgreSQL 17 + Prisma ORM 6 / Drizzle ORM - 缓存:Redis 8 - 认证:JWT(RS256)+ OAuth 2.0(Authorization Code + PKCE) - 测试:Vitest + Supertest + Testcontainers - 构建:tsup / esbuild - 包管理器:pnpm ## 安全强制规则(最高优先级) ### SQL 注入防护 - 所有数据库查询必须使用参数化查询或 ORM - 禁止字符串拼接 SQL:禁止 `SELECT * FROM users WHERE id = '${id}'` - 禁止使用 Prisma.$queryRawUnsafe() 或 Drizzle sql.raw() 拼接用户输入 - 动态查询(排序字段、筛选条件)必须使用白名单验证 - 原生 SQL 仅在 ORM 无法表达时使用,且必须用参数占位符($1, $2) ### 认证与授权 - 所有 API 端点默认需要认证,公开端点必须显式标注 - JWT 必须使用 RS256(非对称)签名,禁止 HS256 + 硬编码密钥 - JWT 过期时间:access token ≤ 15 分钟,refresh token ≤ 7 天 - 每个端点必须检查用户权限(RBAC/ABAC),不仅仅是认证 - 禁止在 URL query 参数中传递 token - 密码哈希使用 bcrypt(cost ≥ 12)或 argon2id - 登录失败必须实现账户锁定(5 次失败后锁定 15 分钟) ### 密钥管理 - 所有密钥、密码、API key 必须通过环境变量注入 - 禁止在代码中硬编码任何密钥(包括测试代码中的真实密钥) - .env 文件必须在 .gitignore 中 - 生产环境使用 Vault、AWS Secrets Manager 或类似密钥管理服务 - 数据库连接字符串禁止出现在日志或错误响应中 ### 输入验证 - 所有外部输入(body、query、params、headers)必须在控制器层验证 - 使用 Zod / class-validator 进行 schema 验证 - 验证规则:类型检查 + 长度限制 + 格式校验 + 范围约束 - 文件上传必须验证:类型白名单、大小限制(≤ 10MB)、文件名清洗 - 禁止直接将 req.body 传递给数据库操作(必须经过验证和字段筛选) ### 错误处理 - 使用统一的错误处理中间件 - 生产环境禁止返回堆栈跟踪、SQL 错误详情、内部路径 - 错误响应格式统一:{ error: { code, message, requestId } } - 区分客户端错误(4xx)和服务端错误(5xx) - 未捕获异常必须记录完整堆栈但只返回通用错误消息 - 禁止空 catch 块:catch (e) {} 必须至少记录日志 ### 限流与防护 - 所有公开 API 必须配置速率限制 - 默认限制:100 请求/分钟/IP(可按端点调整) - 登录端点:10 请求/分钟/IP - 注册端点:5 请求/分钟/IP - 文件上传端点:20 请求/分钟/用户 - 使用 express-rate-limit 或 @nestjs/throttler - 返回标准限流头:X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After ## 性能规则 ### 数据库 - 禁止在循环中执行数据库查询(N+1 问题) - 使用 Prisma include/select 或 Drizzle with 进行关联查询 - 列表查询必须分页(默认 20 条,最大 100 条) - 频繁查询的字段必须建立索引 - 大批量操作使用 createMany/updateMany 批量 API - 数据库连接使用连接池(Prisma 默认,pg-pool 手动配置) ### 并发 - 涉及余额、库存等关键数据的更新必须使用数据库事务 + 行锁 - 使用乐观锁(version 字段)或悲观锁(SELECT FOR UPDATE)防止竞态 - 分布式锁使用 Redis(Redlock 算法) - 幂等性:支付、订单创建等操作必须实现幂等键 ### 缓存 - 热点数据使用 Redis 缓存,设置合理的 TTL - 缓存键命名规范:{service}:{entity}:{id},如 user-service:user:123 - 数据变更时主动失效缓存(Cache-Aside 模式) - 禁止缓存敏感数据(密码、token、个人身份信息) ## 代码风格 ### TypeScript - 严格模式:所有文件必须通过 strict TypeScript 检查 - 禁止 any:使用 unknown + 类型守卫 - 接口优先:请求/响应 DTO 使用 interface,工具类型使用 type - 错误类型:自定义错误类继承 Error,包含 statusCode 和 errorCode ### API 设计 - RESTful 命名:复数名词(/users, /orders),HTTP 动词表达操作 - 版本化:URL 前缀 /api/v1/ - 响应格式统一:{ data, meta, error } - 分页格式:{ data: [], meta: { total, page, pageSize, totalPages } } - 日期格式:ISO 8601(UTC) - ID 格式:UUID v7(时间有序)或 CUID2 ### 文件组织 - 控制器:src/modules/{module}/controller.ts - 服务层:src/modules/{module}/service.ts - 数据访问:src/modules/{module}/repository.ts - DTO/验证:src/modules/{module}/dto.ts - 路由:src/modules/{module}/routes.ts - 中间件:src/middleware/ - 工具函数:src/lib/ 或 src/utils/ - 类型定义:src/types/ ## 日志与审计 - 使用结构化日志(pino / winston),JSON 格式 - 日志级别:error > warn > info > debug - 必须记录:认证事件、权限变更、数据修改、API 错误 - 禁止在日志中记录:密码、token、信用卡号、身份证号 - 每个请求必须有唯一 requestId(通过中间件注入) - 生产环境日志级别:info ## 禁止行为 - 禁止使用 eval()、new Function()、child_process.exec() 处理用户输入 - 禁止在响应中返回数据库内部 ID(使用 UUID) - 禁止 SELECT *(必须显式指定需要的字段) - 禁止在 GET 请求中执行写操作 - 禁止信任 X-Forwarded-For 头(除非在可信代理后) - 禁止使用 cors({ origin: '*' }) 在生产环境 - 禁止将用户上传文件存储在应用服务器本地(使用 S3/R2)

2.2 Kiro Steering 后端规则模板

Kiro 支持分层 Steering 文件,可以按关注点拆分规则。以下是后端项目推荐的文件结构:

.kiro/ └── steering/ ├── backend-general.md # 通用后端规则(inclusion: always) ├── security-rules.md # 安全规则(inclusion: always) ├── database-rules.md # 数据库规则(inclusion: auto) ├── api-design.md # API 设计规范(inclusion: auto) └── error-handling.md # 错误处理规则(inclusion: auto)

.kiro/steering/backend-general.md

--- inclusion: always description: 后端项目通用规则,适用于所有后端代码交互 globs: "src/**/*.ts" --- # 后端通用规则 ## 技术栈 - Node.js 22 LTS + TypeScript strict mode - Express 5 / Fastify 5 / NestJS 11 - PostgreSQL 17 + Prisma ORM 6 - Redis 8 缓存 - Vitest 测试框架 ## 核心约束 1. 所有外部输入必须验证(Zod schema) 2. 所有数据库查询必须使用参数化查询或 ORM 3. 所有密钥通过环境变量注入,禁止硬编码 4. 所有 API 端点默认需要认证 5. 所有公开端点必须配置速率限制 6. 错误响应禁止泄露内部实现细节 ## 文件命名 - 模块目录:src/modules/{moduleName}/ - 控制器:controller.ts - 服务层:service.ts - 数据访问:repository.ts - DTO/验证:dto.ts - 测试:*.test.ts

.kiro/steering/security-rules.md

--- inclusion: always description: 安全强制规则,适用于所有后端代码 globs: "src/**/*.ts" --- # 安全强制规则 ## SQL 注入防护 - 禁止字符串拼接 SQL 查询 - 动态查询条件使用白名单验证 - ORM 的 raw query 必须使用参数占位符 ## 认证与授权 - JWT 使用 RS256 签名,access token ≤ 15 分钟 - 每个端点必须检查用户权限(不仅仅是认证) - 密码使用 bcrypt(cost ≥ 12)或 argon2id ## 密钥管理 - 所有密钥通过环境变量或密钥管理服务注入 - .env 必须在 .gitignore 中 - 禁止在日志或错误响应中暴露连接字符串 ## 输入验证 - 所有外部输入必须在控制器层用 Zod 验证 - 文件上传:类型白名单 + 大小限制 + 文件名清洗 - 禁止直接将 req.body 传递给数据库操作 ## 输出安全 - 生产环境禁止返回堆栈跟踪 - 响应中禁止包含数据库内部 ID - 设置安全响应头(Helmet 中间件)

.kiro/steering/database-rules.md

--- inclusion: auto description: 数据库访问和查询规则 globs: "src/**/*.ts" --- # 数据库规则 ## 查询优化 - 禁止在循环中执行数据库查询(N+1 问题) - 使用 Prisma include/select 进行关联查询 - 列表查询必须分页(默认 20,最大 100) - 禁止 SELECT *,显式指定需要的字段 - 频繁查询的字段必须建立索引 ## 事务与并发 - 涉及关键数据更新必须使用数据库事务 - 使用乐观锁(version 字段)或悲观锁防止竞态 - 批量操作使用 createMany/updateMany ## 迁移 - 每次 schema 变更必须生成迁移文件 - 迁移文件必须可回滚 - 禁止在迁移中执行不可逆的数据删除(先软删除)

.kiro/steering/api-design.md

--- inclusion: auto description: API 设计规范 globs: "src/modules/**/controller.ts,src/modules/**/routes.ts" --- # API 设计规范 ## RESTful 约定 - URL 使用复数名词:/users, /orders, /products - HTTP 动词:GET(读)POST(创建)PUT(全量更新)PATCH(部分更新)DELETE(删除) - 版本化:/api/v1/ 前缀 - 嵌套资源最多 2 层:/users/:id/orders ## 响应格式 - 成功:{ data: T, meta?: { total, page, pageSize } } - 错误:{ error: { code: string, message: string, requestId: string } } - 分页:使用 page + pageSize 参数,返回 total 和 totalPages - 日期:ISO 8601 UTC 格式 - ID:UUID v7 或 CUID2 ## 限流 - 所有公开端点必须配置速率限制 - 返回标准限流头:X-RateLimit-Limit, X-RateLimit-Remaining, Retry-After

.kiro/steering/error-handling.md

--- inclusion: auto description: 错误处理规范 globs: "src/**/*.ts" --- # 错误处理规范 ## 错误类 - 自定义 AppError 基类,包含 statusCode、errorCode、message - 业务错误继承 AppError:NotFoundError、ValidationError、UnauthorizedError、ForbiddenError - 区分可预期错误(业务逻辑)和不可预期错误(系统故障) ## 错误中间件 - 全局错误处理中间件捕获所有未处理错误 - 可预期错误:返回具体错误信息和对应 HTTP 状态码 - 不可预期错误:记录完整堆栈,返回 500 + 通用错误消息 - 禁止空 catch 块 ## 日志 - 错误日志必须包含:requestId、userId、错误类型、堆栈跟踪 - 禁止在日志中记录敏感数据(密码、token、PII)

2.3 Cursor Rules 后端规则模板

.cursor/rules/backend.mdc

--- description: 后端开发通用规则 globs: ["src/**/*.ts", "prisma/**/*.prisma"] --- # 后端开发规则 ## 技术栈约束 - 运行时:Node.js 22 + TypeScript(strict mode) - 框架:Express 5 / Fastify 5 / NestJS 11 - 数据库:PostgreSQL 17 + Prisma ORM 6 - 缓存:Redis 8 - 测试:Vitest + Supertest ## 安全规则(最高优先级) 1. 所有数据库查询使用参数化查询或 ORM,禁止字符串拼接 SQL 2. 所有密钥通过环境变量注入,禁止硬编码 3. 所有外部输入必须用 Zod 验证 4. JWT 使用 RS256 签名,access token ≤ 15 分钟 5. 每个端点必须检查认证和授权 6. 所有公开 API 必须配置速率限制 7. 错误响应禁止泄露堆栈跟踪和内部路径 8. 禁止 eval()、new Function() 处理用户输入 ## 数据库规则 1. 禁止在循环中执行查询(N+1) 2. 列表查询必须分页 3. 禁止 SELECT * 4. 关键数据更新使用事务 + 锁 5. 频繁查询字段建立索引 ## API 设计 1. RESTful 命名:复数名词 + HTTP 动词 2. 版本化:/api/v1/ 3. 统一响应格式:{ data, meta, error } 4. 日期使用 ISO 8601 UTC ## 错误处理 1. 使用自定义错误类(AppError) 2. 全局错误中间件 3. 禁止空 catch 块 4. 生产环境不返回堆栈跟踪

2.4 三大平台后端规则对比

特性CLAUDE.mdKiro SteeringCursor Rules
安全规则加载始终加载(全量)always inclusion(始终加载)按 glob 匹配加载
规则分层单文件,按章节分多文件,按关注点拆分多文件,按 glob 匹配
最佳实践安全规则放最前面security-rules.md 设为 always安全规则放在文件顶部
上下文消耗中等(全量加载)低(按需加载非安全规则)低(按 glob 匹配)
推荐场景单人/小团队项目中大型团队,规范化流程日常开发,快速迭代

2.5 操作步骤:为后端项目添加 Steering 规则

步骤 1:审计现有项目安全状态

# 检查项目技术栈 cat package.json | jq '.dependencies, .devDependencies' # 检查是否有硬编码密钥 grep -rn "password\|secret\|api_key\|apiKey\|API_KEY\|token" src/ --include="*.ts" | grep -v "node_modules\|.test.\|.spec." # 检查是否有字符串拼接 SQL grep -rn "queryRawUnsafe\|sql\.raw\|\`SELECT.*\${\|\`INSERT.*\${\|\`UPDATE.*\${\|\`DELETE.*\${" src/ --include="*.ts" # 检查是否有 eval 或 Function grep -rn "eval(\|new Function(" src/ --include="*.ts" # 检查依赖漏洞 npx audit-ci --critical # 或 pnpm audit --audit-level=critical # 检查现有 AI 规则文件 ls -la CLAUDE.md .cursorrules .cursor/rules/ .kiro/steering/

步骤 2:选择规则平台并创建规则文件

根据团队使用的 AI 工具选择对应的规则文件格式。复制上述模板,根据项目实际情况修改:

  • 替换技术栈信息(框架、ORM、数据库)
  • 添加项目特定的安全约束(如金融项目的加密要求)
  • 添加业务领域特定的规则(如电商的支付安全规则)

步骤 3:渐进式完善

不要试图一次写完所有规则。推荐流程:

  1. 先写安全强制规则(SQL 注入、认证、密钥管理)——这是最高优先级
  2. 使用 AI 开发一周,记录 AI 犯的安全和性能错误
  3. 针对每个重复出现的错误,添加对应的规则
  4. 每两周审查一次规则,删除过时或冗余的条目

步骤 4:集成到 CI/CD

将安全规则的验证集成到 CI/CD 流水线中(详见第 4 节自动化检测)。

提示词模板:分析后端项目并生成 Steering 规则

请分析我的后端项目并生成适合的 Steering 规则。 项目信息: - package.json 中的依赖:[粘贴依赖列表] - 目录结构:[粘贴 tree 输出] - 数据库类型:[PostgreSQL / MySQL / MongoDB] - ORM:[Prisma / Drizzle / TypeORM / Sequelize] - 认证方案:[JWT / Session / OAuth] - 部署环境:[AWS / GCP / Vercel / Railway / 自建服务器] - 团队规模:[人数] - 目标 AI 工具:[Claude Code / Kiro / Cursor] 请生成: 1. 安全强制规则(SQL 注入、认证、密钥管理、输入验证) 2. 数据库访问规则(N+1 防护、分页、事务) 3. API 设计规范(RESTful、响应格式、版本化) 4. 错误处理规范(错误类、中间件、日志) 5. 限流与防护规则 6. 禁止行为清单 输出格式:[CLAUDE.md / Kiro Steering / Cursor Rules]

3. 十大后端反模式详解

AI 生成后端代码时最常见的十大反模式,每个反模式包含:问题描述、AI 犯错原因、识别方法、Steering 规则防护、修复 prompt 模板。

3.1 反模式一:SQL 注入(SQL Injection)

问题描述

AI 生成的数据库查询代码经常使用字符串拼接构建 SQL,将用户输入直接嵌入查询语句。这是 OWASP API Security Top 10 中最经典的漏洞之一。典型表现:

  • 使用模板字符串拼接 SQL:`SELECT * FROM users WHERE email = '${email}'`
  • 在 ORM 的 raw query 中拼接用户输入
  • 动态排序/筛选字段直接拼接到 ORDER BY 或 WHERE 子句
  • 搜索功能使用 LIKE ’%${keyword}%’ 拼接

AI 犯错原因

AI 训练数据中包含大量使用字符串拼接的 SQL 示例(尤其是教程和 Stack Overflow 回答)。字符串拼接是最”直观”的写法,AI 倾向于选择最简洁的实现方式。当 prompt 中没有明确要求安全性时,AI 默认选择最短路径。

识别方法

# 检测字符串拼接 SQL(模板字符串) grep -rn "\`SELECT.*\${\|\`INSERT.*\${\|\`UPDATE.*\${\|\`DELETE.*\${" src/ --include="*.ts" # 检测 Prisma 不安全原生查询 grep -rn "queryRawUnsafe\|executeRawUnsafe" src/ --include="*.ts" # 检测 Drizzle 不安全原生 SQL grep -rn "sql\.raw\b" src/ --include="*.ts" | grep -v "sql\.raw\`" # 使用 Semgrep 自动检测 npx semgrep --config "p/sql-injection" src/ # 使用 ESLint 安全插件 npx eslint src/ --rule '{"no-eval": "error"}'

Steering 规则防护

## SQL 注入防护规则 - 所有数据库查询必须使用参数化查询或 ORM 方法 - 禁止:`SELECT * FROM users WHERE id = '${id}'` - 正确:prisma.user.findUnique({ where: { id } }) - 禁止:Prisma.$queryRawUnsafe() 拼接用户输入 - 正确:Prisma.$queryRaw`SELECT * FROM users WHERE id = ${id}`(tagged template) - 动态排序字段必须使用白名单: const ALLOWED_SORT = ['createdAt', 'name', 'email'] as const if (!ALLOWED_SORT.includes(sortBy)) throw new ValidationError() - 搜索功能使用 ORM 的 contains/like 方法,不要手写 LIKE 查询

修复 Prompt 模板

请审查以下后端代码,检测并修复所有 SQL 注入漏洞: [粘贴代码] 检查项: 1. 是否有字符串拼接构建的 SQL 查询?→ 改为参数化查询或 ORM 方法 2. 是否有 $queryRawUnsafe 或 sql.raw 拼接用户输入?→ 改为 tagged template 3. 动态排序/筛选字段是否经过白名单验证?→ 添加白名单 4. 搜索功能是否安全?→ 使用 ORM 的 contains 方法 5. 是否有其他用户输入直接进入数据库操作的路径? 请输出修复后的代码,并解释每处修改的安全原因。

3.2 反模式二:认证绕过(Authentication Bypass)

问题描述

AI 生成的认证代码经常存在绕过漏洞:JWT 使用弱签名算法、缺少 token 过期验证、权限检查不完整、密码存储不安全。典型表现:

  • JWT 使用 HS256 + 硬编码密钥(如 jwt.sign(payload, 'secret')
  • 缺少 token 过期时间或过期时间过长(30 天)
  • 只检查认证(用户是否登录)不检查授权(用户是否有权限)
  • 密码使用 MD5/SHA256 哈希(无盐值)
  • 重置密码 token 不过期或可重复使用
  • 登录接口无失败次数限制

AI 犯错原因

AI 训练数据中大量教程使用简化的认证实现(jwt.sign(payload, 'secret')),这些代码在教学场景下可行但不适合生产环境。AI 倾向于实现”能工作”的最小方案,而安全加固需要额外的代码和配置。

识别方法

# 检测硬编码 JWT 密钥 grep -rn "jwt\.sign.*['\"].*['\"]" src/ --include="*.ts" grep -rn "jwt\.verify.*['\"].*['\"]" src/ --include="*.ts" # 检测弱哈希算法 grep -rn "md5\|sha1\|sha256" src/ --include="*.ts" | grep -i "password\|hash" # 检测缺少过期时间的 JWT grep -rn "jwt\.sign" src/ --include="*.ts" | grep -v "expiresIn" # 检测缺少权限检查的路由 grep -rn "router\.\(get\|post\|put\|patch\|delete\)" src/ --include="*.ts" | grep -v "auth\|guard\|middleware\|protect" # 使用 Semgrep 检测认证问题 npx semgrep --config "p/jwt" src/

Steering 规则防护

## 认证与授权规则 - JWT 签名算法必须使用 RS256(非对称),禁止 HS256 + 硬编码密钥 - JWT 密钥必须从环境变量加载:process.env.JWT_PRIVATE_KEY - access token 过期时间 ≤ 15 分钟,refresh token ≤ 7 天 - 每个路由必须有认证中间件,公开路由必须显式标注 @Public() - 认证之后必须检查授权:用户是否有权访问该资源 - 示例:GET /users/:id 必须验证 req.user.id === params.id 或 req.user.role === 'admin' - 密码哈希使用 bcrypt(cost ≥ 12)或 argon2id,禁止 MD5/SHA 系列 - 重置密码 token 必须一次性使用且 15 分钟过期 - 登录失败 5 次后锁定账户 15 分钟

修复 Prompt 模板

请审查以下认证相关代码,检测并修复认证绕过漏洞: [粘贴认证相关代码] 检查项: 1. JWT 签名算法是否安全?→ 改为 RS256 2. JWT 密钥是否硬编码?→ 改为环境变量 3. token 是否有合理的过期时间?→ access ≤ 15min, refresh ≤ 7d 4. 是否所有端点都有认证检查?→ 添加认证中间件 5. 是否有授权检查(不仅仅是认证)?→ 添加权限验证 6. 密码哈希算法是否安全?→ 使用 bcrypt/argon2id 7. 是否有登录失败限制?→ 添加账户锁定机制 请输出修复后的代码。

3.3 反模式三:密钥泄露(Secret Exposure)

问题描述

AI 生成的代码经常在源码中硬编码敏感信息:数据库密码、API 密钥、JWT 密钥、第三方服务凭证。这些信息一旦提交到 Git 仓库,即使后续删除也会留在历史记录中。典型表现:

  • 代码中直接写 const DB_URL = 'postgresql://user:password@localhost:5432/db'
  • 配置文件中硬编码 API 密钥:const STRIPE_KEY = 'sk_live_...'
  • .env 文件被提交到 Git 仓库
  • 测试代码中使用真实的第三方 API 密钥
  • 错误日志中打印数据库连接字符串
  • Docker Compose 文件中硬编码密码

AI 犯错原因

AI 生成的示例代码通常使用硬编码值来保持代码的”完整性”和”可运行性”。AI 不了解项目的 .gitignore 配置,也不会主动检查密钥是否会被提交。在生成 Docker Compose 或配置文件时,AI 倾向于提供”开箱即用”的完整配置。

识别方法

# 检测硬编码密钥(通用模式) grep -rn "password.*=.*['\"].*['\"]" src/ --include="*.ts" | grep -v "test\|spec\|mock\|example" grep -rn "secret.*=.*['\"].*['\"]" src/ --include="*.ts" grep -rn "api_key\|apiKey\|API_KEY" src/ --include="*.ts" | grep -v "process\.env" # 检测数据库连接字符串 grep -rn "postgresql://\|mysql://\|mongodb://" src/ --include="*.ts" # 检测 .env 是否在 .gitignore 中 grep "\.env" .gitignore # 使用 git-secrets 扫描 git secrets --scan # 使用 trufflehog 扫描 Git 历史 trufflehog git file://. --only-verified # 使用 Gitleaks 扫描 gitleaks detect --source . --verbose

Steering 规则防护

## 密钥管理规则 - 所有密钥、密码、API key 必须通过 process.env 读取 - 禁止在代码中出现任何硬编码的密钥值(包括示例值如 'your-api-key') - 配置文件模板使用占位符:DATABASE_URL=postgresql://user:${DB_PASSWORD}@host/db - .env 文件必须在 .gitignore 中,提供 .env.example 作为模板 - .env.example 中的值必须是占位符,不能是真实密钥 - Docker Compose 中的密钥使用 ${VAR} 引用环境变量 - 测试代码使用 mock 值或测试专用密钥,不使用生产密钥 - 日志中禁止打印:密码、token、连接字符串、API 密钥 - 错误响应中禁止包含连接字符串或内部配置信息 - 生产环境使用密钥管理服务(Vault、AWS Secrets Manager、Doppler)

修复 Prompt 模板

请审查以下代码,检测并修复所有密钥泄露问题: [粘贴代码] 检查项: 1. 是否有硬编码的密码、API 密钥、连接字符串?→ 改为 process.env 2. .env 文件是否在 .gitignore 中?→ 添加到 .gitignore 3. 是否提供了 .env.example?→ 创建模板文件 4. 日志中是否打印了敏感信息?→ 过滤敏感字段 5. 错误响应中是否泄露了内部配置?→ 返回通用错误消息 6. Docker Compose 中是否硬编码了密码?→ 使用环境变量引用 7. 测试代码是否使用了真实密钥?→ 改为 mock 值 请输出修复后的代码,并提供 .env.example 模板。

3.4 反模式四:N+1 查询(N+1 Query Problem)

问题描述

AI 生成的数据库访问代码经常产生 N+1 查询问题:先查询一个列表(1 次查询),然后对列表中的每个元素分别查询关联数据(N 次查询)。在小数据量下不明显,但在生产环境中可能导致数百甚至数千次数据库查询。典型表现:

  • 在 for 循环中调用 prisma.user.findUnique() 查询每个用户的订单
  • 在 map/forEach 中执行异步数据库查询
  • GraphQL resolver 中每个字段独立查询数据库
  • 嵌套关联数据逐层查询而非一次性加载
  • API 返回列表时,每条记录的关联数据单独查询

AI 犯错原因

AI 倾向于用最直观的方式解决问题——需要每个用户的订单?遍历用户列表,逐个查询。这种写法逻辑清晰、代码简洁,但性能灾难。AI 缺乏对数据库查询成本的感知,不会主动考虑查询合并。

识别方法

# 检测循环中的数据库查询 grep -rn "for.*await.*prisma\|forEach.*await.*prisma\|map.*await.*prisma" src/ --include="*.ts" # 检测 Promise.all 包裹的多次查询(可能是 N+1 的"优化"版本) grep -rn "Promise\.all.*map.*prisma\|Promise\.all.*map.*findUnique\|Promise\.all.*map.*findFirst" src/ --include="*.ts" # 使用 Prisma 查询日志检测 # 在 prisma client 初始化时启用日志: # new PrismaClient({ log: ['query'] }) # 然后观察单个 API 请求产生的查询数量 # 使用 prisma-query-log 中间件 # 或在测试中使用 jest-prisma 检测查询次数

Steering 规则防护

## N+1 查询防护规则 - 禁止在循环(for/forEach/map)中执行数据库查询 - 需要关联数据时使用 Prisma include 或 Drizzle with 一次性加载 - 错误:users.map(u => prisma.order.findMany({ where: { userId: u.id } })) - 正确:prisma.user.findMany({ include: { orders: true } }) - 需要部分字段时使用 select 限制返回字段 - 批量查询使用 WHERE IN:prisma.user.findMany({ where: { id: { in: userIds } } }) - GraphQL 使用 DataLoader 批量加载关联数据 - 列表 API 的关联数据在 repository 层一次性加载,不在 controller 层逐条查询 - 开发环境启用 Prisma 查询日志,监控每个请求的查询次数 - 单个 API 请求的数据库查询次数不应超过 10 次

修复 Prompt 模板

请审查以下数据库访问代码,检测并修复 N+1 查询问题: [粘贴代码] 项目使用 [Prisma / Drizzle / TypeORM] ORM。 检查项: 1. 是否有循环中的数据库查询?→ 改为 include/with 关联查询 2. 是否有 Promise.all + map 的批量单条查询?→ 改为 WHERE IN 批量查询 3. 关联数据是否在正确的层级加载?→ 在 repository 层一次性加载 4. 是否有不必要的嵌套查询?→ 合并为单次查询 5. 列表 API 是否高效?→ 使用 include + select 限制字段 请输出优化后的代码,并估算优化前后的查询次数对比。

3.5 反模式五:缺少输入验证(Missing Input Validation)

问题描述

AI 生成的 API 端点经常缺少服务端输入验证:直接信任客户端发送的数据、缺少类型检查、缺少长度限制、缺少格式校验。典型表现:

  • 直接将 req.body 传递给数据库操作:prisma.user.create({ data: req.body })
  • 缺少必填字段检查:用户可以提交空的 email 或 name
  • 缺少类型检查:期望数字但接收到字符串
  • 缺少长度限制:用户名可以是 10000 个字符
  • 缺少格式校验:email 字段接受任意字符串
  • 文件上传没有类型和大小限制
  • 路径参数没有验证:/users/:id 的 id 可以是任意字符串

AI 犯错原因

AI 倾向于生成”快乐路径”代码——假设所有输入都是合法的。添加验证逻辑会增加代码量,AI 在没有明确要求时会跳过。AI 训练数据中的教程代码通常省略验证以保持简洁。

识别方法

# 检测直接使用 req.body 的数据库操作 grep -rn "req\.body" src/ --include="*.ts" | grep -i "create\|update\|insert" # 检测缺少验证的路由处理函数 # 查找直接从 req 取值而没有经过验证中间件的路由 grep -rn "req\.body\.\|req\.query\.\|req\.params\." src/ --include="*.ts" | grep -v "validate\|schema\|zod\|class-validator\|joi" # 检测文件上传是否有限制 grep -rn "multer\|upload\|formidable" src/ --include="*.ts" | grep -v "limits\|fileFilter\|maxFileSize" # 使用 Semgrep 检测缺少验证的端点 npx semgrep --config "p/express" src/

Steering 规则防护

## 输入验证规则 - 所有 API 端点的输入必须在控制器层使用 Zod schema 验证 - 每个端点定义独立的请求 schema:CreateUserSchema、UpdateUserSchema - 验证规则必须包含: - 类型检查(string, number, boolean, array) - 必填/可选标记 - 字符串长度限制(name: z.string().min(1).max(100)) - 数字范围限制(age: z.number().int().min(0).max(150)) - 格式校验(email: z.string().email()) - 枚举值限制(role: z.enum(['user', 'admin'])) - 禁止直接将 req.body 传递给数据库操作 - 使用 schema.parse(req.body) 的返回值(经过验证和类型转换的数据) - 路径参数必须验证格式:id 必须是有效的 UUID - 文件上传必须配置: - 类型白名单:['image/jpeg', 'image/png', 'application/pdf'] - 大小限制:≤ 10MB - 文件名清洗:移除特殊字符和路径遍历字符 - 分页参数必须有默认值和上限:page ≥ 1, pageSize ∈ [1, 100]

修复 Prompt 模板

请为以下 API 端点添加完整的输入验证: [粘贴路由和控制器代码] 要求: 1. 使用 Zod 定义请求 schema(body、query、params 分别验证) 2. 包含类型检查、长度限制、格式校验、枚举值限制 3. 路径参数 id 验证为 UUID 格式 4. 分页参数有默认值和上限 5. 验证失败返回 400 + 具体的错误信息 6. 使用验证后的数据(而非原始 req.body)进行数据库操作 请输出完整的 Zod schema 定义和验证中间件代码。

3.6 反模式六:错误处理不当(Improper Error Handling)

问题描述

AI 生成的错误处理代码经常存在严重问题:泄露内部实现细节、吞掉关键错误、使用通用 catch-all、缺少错误分类。典型表现:

  • 直接返回数据库错误信息:res.status(500).json({ error: err.message })(可能包含 SQL 语句和表结构)
  • 返回完整堆栈跟踪:res.status(500).json({ stack: err.stack })
  • 空 catch 块:catch (e) {} 吞掉所有错误
  • 所有错误都返回 500:不区分 400(客户端错误)和 500(服务端错误)
  • 缺少全局错误处理中间件:未捕获的异常导致进程崩溃
  • 异步错误未被捕获:Express 中 async 函数的错误不会自动传递给错误中间件

AI 犯错原因

AI 生成的错误处理通常是”最小可行”的——一个 try-catch 包裹所有逻辑,catch 中直接返回 err.message。AI 不了解生产环境的安全要求(不能泄露内部信息),也不会主动设计错误分类体系。

识别方法

# 检测直接返回错误消息 grep -rn "err\.message\|error\.message\|e\.message" src/ --include="*.ts" | grep "res\.\|json\|send" # 检测返回堆栈跟踪 grep -rn "err\.stack\|error\.stack\|e\.stack" src/ --include="*.ts" | grep "res\.\|json\|send" # 检测空 catch 块 grep -rn "catch.*{.*}" src/ --include="*.ts" | grep -v "log\|throw\|return\|console\|next" # 检测缺少 async 错误处理 grep -rn "async.*req.*res" src/ --include="*.ts" | grep -v "try\|asyncHandler\|catchAsync" # 检测所有错误都返回 500 grep -rn "status(500)" src/ --include="*.ts" | wc -l grep -rn "status(4[0-9][0-9])" src/ --include="*.ts" | wc -l # 如果 500 远多于 4xx,说明错误分类不足

Steering 规则防护

## 错误处理规则 - 定义自定义错误基类 AppError,包含 statusCode、errorCode、message - 业务错误类: - NotFoundError (404) - ValidationError (400) - UnauthorizedError (401) - ForbiddenError (403) - ConflictError (409) - RateLimitError (429) - 全局错误处理中间件: - AppError 实例:返回对应 statusCode + errorCode + message - Zod 验证错误:返回 400 + 格式化的字段错误 - Prisma 已知错误(P2002 唯一约束):返回 409 + 友好消息 - 未知错误:记录完整堆栈,返回 500 + 通用消息 "Internal Server Error" - 生产环境禁止返回:堆栈跟踪、SQL 错误详情、文件路径、环境变量 - 所有错误响应包含 requestId 用于追踪 - 禁止空 catch 块:至少记录日志或重新抛出 - Express async 路由必须使用 asyncHandler 包装或 express-async-errors - 未捕获异常和未处理 Promise rejection 必须有全局处理器

修复 Prompt 模板

请审查以下后端代码的错误处理,检测并修复问题: [粘贴代码] 检查项: 1. 是否泄露了内部错误信息(SQL 错误、堆栈跟踪、文件路径)?→ 返回通用消息 2. 是否有空 catch 块?→ 添加日志记录 3. 是否区分了客户端错误和服务端错误?→ 使用自定义错误类 4. 是否有全局错误处理中间件?→ 添加统一错误处理 5. async 路由的错误是否被正确捕获?→ 使用 asyncHandler 6. 是否有未处理的 Promise rejection?→ 添加全局处理器 请输出: 1. 自定义错误类定义 2. 全局错误处理中间件 3. 修复后的路由代码

3.7 反模式七:竞态条件(Race Conditions)

问题描述

AI 生成的代码通常不考虑并发场景,导致竞态条件和数据不一致。在高并发环境下,多个请求同时修改同一数据可能导致数据丢失、超卖、重复扣款等严重问题。典型表现:

  • 先读后写模式(Read-Modify-Write)没有加锁:
    const user = await prisma.user.findUnique({ where: { id } }); await prisma.user.update({ where: { id }, data: { balance: user.balance - amount } }); // 两个并发请求可能读到相同的 balance,导致只扣一次
  • 库存扣减没有使用原子操作
  • 订单创建没有幂等性保护,重复提交创建多个订单
  • 分布式环境下缺少分布式锁
  • 数据库事务隔离级别不当

AI 犯错原因

AI 生成的代码默认在单线程、单请求的心智模型下工作。并发问题需要对系统的运行时行为有深入理解,这超出了 AI 基于代码模式匹配的能力。AI 训练数据中的教程代码几乎不涉及并发控制。

识别方法

# 检测先读后写模式(潜在竞态) grep -rn "findUnique\|findFirst" src/ --include="*.ts" -A 5 | grep "update\|delete" # 检测余额/库存相关操作(高风险区域) grep -rn "balance\|stock\|inventory\|quantity\|credits" src/ --include="*.ts" | grep "update\|decrement\|increment" # 检测缺少事务的多步操作 grep -rn "await.*prisma\." src/ --include="*.ts" -A 3 | grep -B 1 "await.*prisma\." | grep -v "\$transaction" # 检测缺少幂等键的创建操作 grep -rn "create(" src/ --include="*.ts" | grep -i "order\|payment\|transaction" | grep -v "idempotency\|idempotent"

Steering 规则防护

## 并发与竞态防护规则 - 涉及余额、库存、积分等关键数据的更新必须使用以下方式之一: 1. 数据库原子操作:prisma.user.update({ data: { balance: { decrement: amount } } }) 2. 事务 + 悲观锁:$transaction + SELECT FOR UPDATE 3. 乐观锁:version 字段 + WHERE version = expectedVersion - 禁止先读后写模式(Read-Modify-Write)处理关键数据 - 支付、订单创建等操作必须实现幂等性: - 客户端生成幂等键(Idempotency-Key header) - 服务端在处理前检查幂等键是否已处理 - 使用数据库唯一约束保证幂等 - 分布式环境使用 Redis 分布式锁(Redlock) - 数据库事务使用 Serializable 隔离级别处理关键业务 - 所有涉及金额的操作必须在事务中完成 - 并发测试:关键业务逻辑必须有并发测试用例

修复 Prompt 模板

请审查以下代码的并发安全性,检测并修复竞态条件: [粘贴代码] 业务场景:[描述业务场景,如"用户余额扣减"、"商品库存扣减"、"订单创建"] 检查项: 1. 是否有先读后写模式?→ 改为原子操作或事务+锁 2. 关键数据更新是否在事务中?→ 添加 $transaction 3. 是否需要幂等性保护?→ 添加幂等键机制 4. 是否需要分布式锁?→ 添加 Redis 锁 5. 并发场景下数据是否一致?→ 添加并发测试 请输出修复后的代码,并解释选择的并发控制策略。

3.8 反模式八:缺少限流(Missing Rate Limiting)

问题描述

AI 生成的 API 通常没有任何速率限制,使系统暴露在滥用和攻击风险中。缺少限流的 API 可能被用于暴力破解密码、爬取数据、发起 DDoS 攻击、滥用付费第三方 API。典型表现:

  • 登录接口无限制:攻击者可以无限次尝试密码
  • 注册接口无限制:可以批量注册垃圾账户
  • 搜索/列表接口无限制:可以高速爬取全部数据
  • 文件上传接口无限制:可以耗尽存储空间
  • 调用第三方 API 的端点无限制:可能导致高额账单
  • 缺少全局限流:单个用户可以耗尽服务器资源

AI 犯错原因

限流不是”功能需求”的一部分,AI 在实现业务逻辑时不会主动添加。AI 训练数据中的教程代码几乎不包含限流配置。限流需要对系统的运行环境和威胁模型有理解,这超出了 AI 的代码生成范围。

识别方法

# 检测是否安装了限流中间件 grep -rn "rate-limit\|throttle\|rateLimit" package.json # 检测路由是否配置了限流 grep -rn "rateLimit\|throttle\|RateLimit" src/ --include="*.ts" # 检测登录/注册端点是否有特殊限流 grep -rn "login\|signin\|register\|signup" src/ --include="*.ts" | grep -i "rate\|limit\|throttle" # 检测是否返回限流头 grep -rn "X-RateLimit\|Retry-After\|RateLimit-" src/ --include="*.ts" # 使用 OWASP ZAP 测试限流 # 或使用 ab/wrk 进行压力测试 # ab -n 1000 -c 50 http://localhost:3000/api/v1/login

Steering 规则防护

## 限流与防护规则 - 所有 API 必须配置速率限制,使用 express-rate-limit 或 @nestjs/throttler - 默认限流策略(按 IP): - 全局:100 请求/分钟 - 登录:10 请求/分钟 - 注册:5 请求/分钟 - 密码重置:3 请求/分钟 - 文件上传:20 请求/分钟 - 搜索:30 请求/分钟 - 认证用户可以有更高的限额(按用户 ID 限流) - 返回标准限流响应头: - X-RateLimit-Limit:限额 - X-RateLimit-Remaining:剩余次数 - X-RateLimit-Reset:重置时间 - Retry-After:429 响应时的等待时间 - 限流存储使用 Redis(分布式环境) - 关键端点(登录、支付)使用滑动窗口算法 - 超过限流返回 429 Too Many Requests + 友好错误消息 - Webhook 端点使用签名验证 + IP 白名单

修复 Prompt 模板

请为以下 API 项目添加完整的限流配置: [粘贴路由配置或 app 入口文件] 项目框架:[Express / Fastify / NestJS] 部署环境:[单实例 / 多实例(需要 Redis)] 要求: 1. 全局默认限流:100 请求/分钟/IP 2. 登录端点:10 请求/分钟/IP 3. 注册端点:5 请求/分钟/IP 4. 文件上传:20 请求/分钟/用户 5. 返回标准限流响应头 6. 超过限流返回 429 + 友好错误消息 7. [如果多实例] 使用 Redis 作为限流存储 请输出完整的限流中间件配置代码。

3.9 反模式九:日志安全问题(Insecure Logging)

问题描述

AI 生成的日志代码经常存在安全问题:在日志中记录敏感数据、缺少结构化日志、日志级别不当、缺少请求追踪。典型表现:

  • 日志中记录用户密码:logger.info('User login', { email, password })
  • 日志中记录完整的请求体(可能包含信用卡号、身份证号)
  • 日志中记录 JWT token 或 API 密钥
  • 使用 console.log 而非结构化日志库
  • 生产环境使用 debug 级别日志(性能影响 + 信息泄露)
  • 缺少请求 ID,无法追踪跨服务的请求链路
  • 错误日志缺少上下文信息(用户 ID、请求路径、请求参数)

AI 犯错原因

AI 生成日志代码时倾向于记录”所有可用信息”以便调试。AI 不了解哪些字段是敏感的(密码、token、PII),也不会主动过滤。AI 训练数据中大量使用 console.log,这在生产环境中不适用。

识别方法

# 检测日志中可能包含敏感数据 grep -rn "log.*password\|log.*token\|log.*secret\|log.*apiKey\|log.*creditCard" src/ --include="*.ts" # 检测 console.log 使用(应使用结构化日志) grep -rn "console\.log\|console\.error\|console\.warn" src/ --include="*.ts" | grep -v "node_modules\|test\|spec" # 检测日志中记录完整请求体 grep -rn "log.*req\.body\|log.*request\.body" src/ --include="*.ts" # 检测是否有请求 ID 中间件 grep -rn "requestId\|request-id\|correlationId\|x-request-id" src/ --include="*.ts" # 检测日志库使用 grep -rn "pino\|winston\|bunyan\|log4js" package.json

Steering 规则防护

## 日志安全规则 - 使用结构化日志库(pino 推荐,性能最优),禁止 console.log - 日志格式:JSON,包含 timestamp、level、message、requestId、context - 敏感字段自动脱敏(使用 pino 的 redact 配置): - 密码:password, passwd, pwd - Token:token, accessToken, refreshToken, authorization - 密钥:secret, apiKey, api_key, privateKey - PII:ssn, creditCard, cardNumber - 禁止在日志中记录完整的请求体(仅记录非敏感字段) - 每个请求必须有唯一 requestId(通过中间件注入) - 日志级别规范: - error:系统错误、未捕获异常、第三方服务故障 - warn:业务异常、降级、接近限额 - info:请求开始/结束、关键业务操作(登录、支付、权限变更) - debug:详细调试信息(仅开发环境) - 生产环境日志级别:info - 安全审计日志必须记录:认证事件、权限变更、数据修改、管理员操作

修复 Prompt 模板

请审查以下代码的日志实现,检测并修复日志安全问题: [粘贴代码] 检查项: 1. 日志中是否记录了敏感数据(密码、token、PII)?→ 添加脱敏 2. 是否使用了 console.log?→ 改为结构化日志库(pino) 3. 是否有请求 ID 追踪?→ 添加 requestId 中间件 4. 日志级别是否合理?→ 按规范调整 5. 是否记录了必要的安全审计事件?→ 添加审计日志 6. 生产环境日志级别是否正确?→ 设为 info 请输出: 1. pino 日志配置(含 redact 脱敏规则) 2. requestId 中间件 3. 修复后的日志代码

3.10 反模式十:CORS 与安全头配置不当(Misconfigured CORS & Security Headers)

问题描述

AI 生成的后端代码经常使用过于宽松的 CORS 配置和缺少安全响应头,使应用暴露在跨站攻击风险中。典型表现:

  • 使用 cors({ origin: '*' }) 允许所有来源(生产环境)
  • 缺少 CORS 配置导致前端无法调用 API,然后 AI 直接设置 origin: '*' 作为”修复”
  • 缺少安全响应头:Content-Security-Policy、X-Content-Type-Options、Strict-Transport-Security
  • 允许不必要的 HTTP 方法(OPTIONS 之外的 TRACE、CONNECT)
  • credentials 配置与 origin 不匹配
  • 缺少 CSRF 防护(对于使用 cookie 认证的应用)

AI 犯错原因

CORS 错误是前后端分离开发中最常见的问题之一。当 AI 遇到 CORS 错误时,最快的”修复”就是 origin: '*'。AI 不了解生产环境的安全要求,也不会主动添加安全响应头。安全头的配置需要对 Web 安全有深入理解。

识别方法

# 检测宽松的 CORS 配置 grep -rn "origin.*\*\|origin.*true\|cors()" src/ --include="*.ts" # 检测是否使用了 Helmet(安全头中间件) grep -rn "helmet" package.json src/ --include="*.ts" # 检测安全响应头 curl -I http://localhost:3000/api/v1/health | grep -i "x-content-type\|strict-transport\|content-security\|x-frame" # 检测 CSRF 防护 grep -rn "csrf\|csurf\|csrfToken" src/ --include="*.ts" package.json

Steering 规则防护

## CORS 与安全头规则 - CORS origin 必须使用白名单,禁止 origin: '*'(生产环境) - 正确:origin: ['https://app.example.com', 'https://admin.example.com'] - 开发环境可以使用 origin: 'http://localhost:5173' - 使用 Helmet 中间件设置安全响应头 - 必须配置的安全头: - Strict-Transport-Security: max-age=31536000; includeSubDomains - X-Content-Type-Options: nosniff - X-Frame-Options: DENY(或 SAMEORIGIN) - Content-Security-Policy: default-src 'self' - X-XSS-Protection: 0(现代浏览器已内置,设为 0 避免旧版浏览器的 XSS 过滤器问题) - Referrer-Policy: strict-origin-when-cross-origin - 仅允许必要的 HTTP 方法:GET, POST, PUT, PATCH, DELETE, OPTIONS - 使用 cookie 认证时必须配置 CSRF 防护 - API 响应禁止包含 X-Powered-By 头(Helmet 默认移除)

修复 Prompt 模板

请审查以下后端应用的 CORS 和安全头配置: [粘贴 app 入口文件或中间件配置] 部署环境: - 前端域名:[https://app.example.com] - API 域名:[https://api.example.com] - 认证方式:[JWT Bearer / Cookie Session] 检查项: 1. CORS origin 是否使用白名单?→ 配置具体域名 2. 是否使用了 Helmet 中间件?→ 添加 Helmet 3. 安全响应头是否完整?→ 检查 CSP、HSTS、X-Frame-Options 等 4. 是否允许了不必要的 HTTP 方法?→ 限制为必要方法 5. [如果使用 cookie] 是否有 CSRF 防护?→ 添加 CSRF token 6. 是否暴露了 X-Powered-By?→ 使用 Helmet 移除 请输出完整的安全中间件配置代码。

4. 反模式检测自动化

4.1 CI/CD 集成安全质量门

将后端反模式检测集成到 CI/CD 流水线中,在代码合并前自动拦截安全和性能问题:

# .github/workflows/backend-security.yml name: Backend Security Gate on: pull_request: paths: - 'src/**' - 'prisma/**' - 'package.json' jobs: security-check: runs-on: ubuntu-latest services: postgres: image: postgres:17 env: POSTGRES_USER: test POSTGRES_PASSWORD: test POSTGRES_DB: test ports: - 5432:5432 options: >- --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5 steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: version: 9 - uses: actions/setup-node@v4 with: node-version: 22 cache: 'pnpm' - run: pnpm install --frozen-lockfile # TypeScript 类型检查 - name: Type Check run: pnpm tsc --noEmit # ESLint 安全规则 - name: Lint run: pnpm eslint src/ --max-warnings 0 # 依赖漏洞扫描 - name: Dependency Audit run: pnpm audit --audit-level=high # Semgrep 安全扫描 - name: Semgrep Security Scan uses: semgrep/semgrep-action@v1 with: config: >- p/sql-injection p/jwt p/secrets p/nodejs p/express # 密钥泄露检测 - name: Secret Scan uses: gitleaks/gitleaks-action@v2 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # 单元测试 - name: Unit Tests run: pnpm vitest run --coverage env: DATABASE_URL: postgresql://test:test@localhost:5432/test # 检查测试覆盖率 - name: Coverage Check run: | COVERAGE=$(pnpm vitest run --coverage --reporter=json | jq '.total.lines.pct') echo "Coverage: $COVERAGE%" if (( $(echo "$COVERAGE < 80" | bc -l) )); then echo "❌ Coverage below 80%!" exit 1 fi

4.2 Semgrep 自定义规则

为项目特定的反模式创建 Semgrep 自定义规则:

# .semgrep/backend-rules.yml rules: # 检测字符串拼接 SQL - id: no-sql-string-concat patterns: - pattern: | $QUERY = `... ${$VAR} ...` - metavariable-regex: metavariable: $QUERY regex: ".*(SELECT|INSERT|UPDATE|DELETE|FROM|WHERE).*" message: "禁止字符串拼接 SQL 查询,使用参数化查询或 ORM" severity: ERROR languages: [typescript, javascript] # 检测硬编码密钥 - id: no-hardcoded-secrets patterns: - pattern-either: - pattern: | jwt.sign($PAYLOAD, "...") - pattern: | jwt.verify($TOKEN, "...") message: "禁止硬编码 JWT 密钥,使用环境变量" severity: ERROR languages: [typescript, javascript] # 检测缺少输入验证的路由 - id: missing-input-validation patterns: - pattern: | $ROUTER.$METHOD($PATH, async ($REQ, $RES) => { ... $ORM.create({ data: $REQ.body }) ... }) message: "禁止直接将 req.body 传递给数据库操作,必须先验证" severity: WARNING languages: [typescript, javascript] # 检测空 catch 块 - id: no-empty-catch pattern: | catch ($ERR) { } message: "禁止空 catch 块,至少记录日志" severity: WARNING languages: [typescript, javascript] # 检测 console.log - id: no-console-log pattern: console.log(...) message: "使用结构化日志库(pino),禁止 console.log" severity: WARNING languages: [typescript, javascript] paths: exclude: - "**/*.test.ts" - "**/*.spec.ts" # 检测宽松 CORS - id: no-wildcard-cors pattern: | cors({ origin: "*" }) message: "生产环境禁止 CORS origin: '*',使用域名白名单" severity: ERROR languages: [typescript, javascript]

4.3 Git Hooks 本地检查

使用 Husky + lint-staged 在提交前检查安全问题:

// package.json { "lint-staged": { "src/**/*.ts": [ "eslint --fix --max-warnings 0", "prettier --write" ], "prisma/**/*.prisma": [ "prisma validate" ] } }
# .husky/pre-commit pnpm lint-staged # 检测硬编码密钥 if grep -rn "password.*=.*['\"].*['\"]" src/ --include="*.ts" | grep -v "test\|spec\|mock\|example\|process\.env" | grep -q .; then echo "❌ 检测到硬编码密钥,请使用环境变量" exit 1 fi

4.4 AI 辅助代码审查 Prompt

在 PR 审查时使用以下 prompt 让 AI 检查所有十大后端反模式:

请作为后端安全审查员,审查以下 PR diff,检查十大后端反模式: [粘贴 git diff 输出] 检查清单: 1. ❌ SQL 注入:是否有字符串拼接 SQL?是否有未参数化的查询? 2. ❌ 认证绕过:JWT 算法是否安全?是否有权限检查?密码哈希是否安全? 3. ❌ 密钥泄露:是否有硬编码密钥?.env 是否在 .gitignore 中? 4. ❌ N+1 查询:是否有循环中的数据库查询?关联数据是否一次性加载? 5. ❌ 缺少验证:所有输入是否经过 Zod 验证?文件上传是否有限制? 6. ❌ 错误处理不当:是否泄露内部信息?是否有空 catch?是否区分 4xx/5xx? 7. ❌ 竞态条件:关键数据更新是否有锁?是否有幂等性保护? 8. ❌ 缺少限流:公开 API 是否有速率限制?登录端点是否有特殊限制? 9. ❌ 日志安全:日志中是否有敏感数据?是否使用结构化日志? 10. ❌ CORS/安全头:CORS 是否使用白名单?是否配置了安全响应头? 对每个发现的问题,请标注: - 严重程度:🔴 必须修复(安全漏洞)/ 🟡 建议修复(性能/质量)/ 🟢 可选优化 - 具体位置:文件名 + 行号 - 修复建议:具体的代码修改方案 - OWASP 分类:对应的 OWASP API Security Top 10 编号(如适用)

5. 实战案例:电商订单系统的 Steering 规则实践

场景描述

一个使用 NestJS + TypeScript + Prisma + PostgreSQL 的电商后端项目,需要开发订单创建和支付流程。团队使用 Kiro 进行 Spec-Driven 开发,需要确保 AI 生成的代码满足安全和性能要求。

步骤 1:配置 Steering 规则

在项目中创建 .kiro/steering/ecommerce-backend.md

--- inclusion: always description: 电商后端项目安全与业务规则 globs: "src/**/*.ts" --- # 电商后端规则 ## 技术栈 - NestJS 11 + TypeScript strict - Prisma ORM 6 + PostgreSQL 17 - Redis 8(缓存 + 分布式锁 + 限流存储) - Stripe / 支付宝 支付集成 ## 电商特定安全规则 - 所有金额使用整数(分/cents),禁止浮点数 - 金额计算禁止使用 JavaScript 浮点运算,使用 Decimal.js 或整数运算 - 订单创建必须实现幂等性(Idempotency-Key) - 库存扣减必须使用数据库原子操作 + 事务 - 支付回调必须验证签名(Stripe webhook signature / 支付宝签名验证) - 支付金额必须与订单金额一致(服务端校验,不信任客户端传递的金额) - 订单状态变更必须记录审计日志 - 退款操作必须有管理员审批 + 二次确认 - 用户只能查看和操作自己的订单(ABAC 权限检查) - 订单查询必须分页,禁止一次返回全部订单

步骤 2:AI 生成订单创建服务

使用以下 prompt 生成代码:

请为电商系统生成订单创建服务。 需求: - 用户提交购物车商品列表,创建订单 - 验证库存充足 - 扣减库存(原子操作) - 创建订单记录 - 发起支付 - 支持幂等性(重复提交不创建重复订单) 技术栈:NestJS + Prisma + PostgreSQL + Redis 请遵循项目 Steering 规则生成代码。

步骤 3:审查 AI 生成的代码

AI 生成代码后,使用反模式检测 prompt 审查:

请审查以下订单创建服务代码,检查十大后端反模式: [AI 生成的订单服务代码] 重点检查: 1. 库存扣减是否有竞态条件?(并发下单可能超卖) 2. 订单创建是否有幂等性保护? 3. 金额计算是否使用整数? 4. 输入验证是否完整? 5. 错误处理是否安全? 6. 是否有 N+1 查询? 7. 日志是否安全(不泄露支付信息)?

步骤 4:修复发现的问题

常见的 AI 生成问题及修复:

问题AI 生成的代码修复后的代码
竞态条件先查库存再扣减(两步操作)使用 UPDATE ... SET stock = stock - $1 WHERE stock >= $1(原子操作)
缺少幂等性直接创建订单检查 Idempotency-Key,已存在则返回已有订单
浮点金额price * quantity(浮点)priceInCents * quantity(整数运算)
缺少验证直接使用 req.bodyZod schema 验证:商品 ID 格式、数量范围、地址格式
错误泄露返回 Prisma 错误详情返回友好错误消息 + requestId
N+1 查询循环查询每个商品价格WHERE id IN (...) 批量查询
日志不安全记录完整支付信息脱敏:仅记录支付 ID 和状态

案例分析

这个案例展示了后端 Steering 规则的核心价值:

  1. 安全优先:Steering 规则将安全约束前置到代码生成阶段,而非事后修复
  2. 业务特定规则:电商场景的金额处理、库存管理、支付安全等规则是通用安全规则之外的业务层约束
  3. 并发意识:通过规则强制要求关键操作使用事务和锁,避免 AI 生成的”快乐路径”代码在生产环境出问题
  4. 审计合规:订单和支付操作的审计日志是合规要求,Steering 规则确保 AI 不会遗漏

6. 后端安全检查清单

以下是一份可直接用于代码审查的后端安全检查清单,覆盖十大反模式:

🔴 必须检查(安全漏洞)

#检查项通过标准对应反模式
1SQL 查询是否参数化无字符串拼接 SQLSQL 注入
2JWT 签名算法RS256(非 HS256)认证绕过
3JWT 密钥来源环境变量(非硬编码)密钥泄露
4密码哈希算法bcrypt/argon2id(非 MD5/SHA)认证绕过
5所有端点有认证检查公开端点显式标注认证绕过
6所有端点有授权检查资源所有权验证认证绕过
7所有输入有验证Zod schema 验证缺少验证
8无硬编码密钥所有密钥来自 env密钥泄露
9.env 在 .gitignore 中已配置密钥泄露
10错误响应不泄露内部信息无堆栈/SQL/路径错误处理
11CORS 使用白名单非 origin: ’*‘CORS 配置
12安全响应头已配置Helmet 中间件CORS 配置

🟡 建议检查(性能与质量)

#检查项通过标准对应反模式
13无 N+1 查询无循环中的 DB 查询N+1 查询
14列表查询有分页默认 20,最大 100N+1 查询
15关键操作有事务金额/库存在事务中竞态条件
16幂等性保护支付/订单有幂等键竞态条件
17API 有速率限制全局 + 端点级限流缺少限流
18登录有失败限制5 次失败锁定缺少限流
19结构化日志pino/winston(非 console.log)日志安全
20日志无敏感数据密码/token 已脱敏日志安全
21请求有 requestId中间件注入日志安全
22无空 catch 块至少记录日志错误处理

避坑指南

❌ 常见错误

  1. 安全规则放在规则文件末尾,AI 可能忽略

    • 问题:AI 的注意力在长文本中会衰减,放在末尾的规则更容易被忽略
    • 正确做法:安全规则放在 Steering 文件的最前面,使用”最高优先级”标注。在 Kiro 中,将安全规则设为 inclusion: always 的独立文件
  2. 只写安全规则不写正确做法

    • 问题:规则只说”禁止字符串拼接 SQL”,AI 不知道应该用什么替代
    • 正确做法:每条禁止规则都配一个正确示例。如”禁止 $queryRawUnsafe() → 使用 $queryRaw tagged template”
  3. 规则与 ORM/框架版本不匹配

    • 问题:规则引用 Prisma 4 的 API,但项目已升级到 Prisma 6
    • 正确做法:每次依赖升级时同步更新 Steering 规则,将规则文件纳入 PR 审查范围
  4. 忽略开发环境与生产环境的差异

    • 问题:开发环境使用 cors({ origin: '*' })console.log,这些配置被 AI 学习并应用到生产代码
    • 正确做法:在规则中明确区分开发和生产环境的配置要求,使用环境变量控制
  5. 过度依赖 Steering 规则而忽略自动化检测

    • 问题:只靠 Steering 规则约束 AI,但 AI 不一定每次都遵守
    • 正确做法:Steering 规则 + CI/CD 自动化检测(Semgrep、Snyk、Gitleaks)双重保障
  6. 没有针对业务场景定制规则

    • 问题:使用通用的后端安全规则,但缺少业务特定的约束(如金融项目的加密要求、医疗项目的 HIPAA 合规)
    • 正确做法:在通用安全规则基础上,添加业务领域特定的规则
  7. 规则过于笼统,缺少具体的代码示例

    • 问题:规则写”必须安全处理密码”,但没有说明具体用什么库、什么参数
    • 正确做法:规则要具体到库名和参数。如”密码使用 bcrypt,cost factor ≥ 12:await bcrypt.hash(password, 12)
  8. 忽略第三方依赖的安全风险

    • 问题:AI 引入的第三方库可能有已知漏洞,但 Steering 规则没有覆盖依赖管理
    • 正确做法:在规则中要求新增依赖前检查漏洞(pnpm audit),并在 CI/CD 中集成依赖扫描

✅ 最佳实践

  1. 安全规则分层:核心安全规则(always)+ 数据库规则(auto)+ API 规则(auto)+ 业务规则(auto)
  2. 规则版本化:将 Steering 规则文件纳入 Git 版本控制,变更需要安全团队审查
  3. 定期安全审计:每月用反模式检测 prompt 审查 AI 生成的代码,发现新问题时更新规则
  4. 自动化双保险:Steering 规则预防 + CI/CD 检测拦截,两道防线确保安全
  5. 团队安全培训:确保团队成员理解每条规则的原因,而非盲目遵守
  6. 渐进式加固:先覆盖 OWASP Top 10,再逐步添加业务特定规则
  7. 规则效果度量:追踪 AI 生成代码的安全问题数量,评估规则的有效性
  8. 跨项目规则复用:将通用安全规则提取为团队级模板,新项目直接复用

相关资源与延伸阅读

  1. OWASP API Security Top 10  — OWASP 官方 API 安全风险清单,后端安全的权威参考(持续更新)
  2. Semgrep Registry  — Semgrep 规则注册表,包含数千条安全检测规则,支持自定义规则(免费开源)
  3. Snyk Vulnerability Database  — Snyk 漏洞数据库,查询 npm 包的已知漏洞(免费查询)
  4. Gitleaks  — 开源密钥泄露检测工具,支持 Git 历史扫描和 CI/CD 集成(GitHub,持续更新)
  5. Helmet.js  — Express/Fastify 安全响应头中间件,一行代码配置 15+ 安全头(免费开源)
  6. express-rate-limit  — Express 限流中间件,支持 Redis 存储和滑动窗口算法(GitHub,持续更新)
  7. Prisma Security Best Practices  — Prisma 官方原生查询安全指南,防止 SQL 注入的最佳实践
  8. Zod  — TypeScript-first 的 schema 验证库,后端输入验证的首选工具(免费开源)
  9. pino  — 高性能 Node.js 结构化日志库,支持 redact 敏感字段脱敏(GitHub,持续更新)
  10. Endor Labs: Design Flaws in AI Generated Code  — AI 生成代码的架构缺陷分析,深入探讨 AI 编码助手引入的系统性安全弱点(2025)

参考来源


📖 返回 总览与导航 | 上一节:28e-微服务与Serverless | 下一节:29a-AI辅助数据库设计概览

Last updated on