AI生成的代码能用。它能运行。看起来没问题。但它也会在几乎每个项目中都带着同样的五个安全漏洞。这些不是理论上的风险——它们是在使用Claude、Cursor、Replit或Copilot生成的几乎每个代码库中都会出现的具体漏洞,除非你明确要求安全性。
过去一年我审计了几十个氛围编码项目,同样的五个错误出现在至少80%的项目中。每个问题修复时间不到30分钟。下面是你需要查找的内容以及修复方法。
错误1:API密钥硬编码在前端代码中
发生方式:你告诉Claude"连接到Supabase"或"添加Stripe支付",它生成的代码直接在React组件中粘贴了API密钥。代码完美运行——但你的密钥对任何打开浏览器DevTools并检查网络标签页或JavaScript源代码的人都是可见的。
为什么危险:你的Supabase服务角色密钥绕过了所有数据库安全。你的Stripe密钥让某人可以刷卡或发起退款。你的OpenAI密钥让某人可以在你的账户上产生数千美元的API调用。机器人会主动扫描公开的GitHub仓库和已部署的网站来寻找泄露的密钥。
修复方法:将每个密钥移到环境变量中。在Next.js中,只有以NEXT_PUBLIC_开头的变量才会到达浏览器。任何授予写访问、管理员访问或财务访问权限的密钥应该仅在服务器端。
将密钥移到.env.local后,搜索整个代码库中的旧密钥值以确保它们已被删除。然后检查你的Git历史——如果密钥曾被提交过,即使你删除了它,它仍然在你的仓库历史中。重新生成(轮换)任何曾被暴露过的密钥,即使只是短暂暴露。
修复时间:15-30分钟。
错误2:Supabase表没有行级安全
发生方式:AI生成了Supabase表创建查询和CRUD操作,但没有启用行级安全(RLS)。默认情况下,禁用RLS的Supabase表对任何拥有你的项目URL和anon密钥的人完全可访问——两者都是公开的(也应该是)。
为什么危险:没有RLS,用户A可以查询用户B的数据。一个简单的fetch调用就可以从浏览器控制台拉取每个表中的每一行。你的整个数据库实际上是公开的。
如何识别:进入你的Supabase仪表板→表编辑器。如果任何表显示"RLS已禁用",你就有这个问题。同时检查你的客户端代码是否使用service_role密钥而不是anon密钥——那就更糟了。
修复方法:在每个表上启用RLS。然后创建与你的应用访问模式相匹配的策略。最常见的策略:用户只能选择、插入、更新和删除auth.uid() = user_id的行。通过以一个用户身份登录并尝试通过Supabase REST API访问另一个用户的数据来测试。
修复时间:30-60分钟,取决于表的数量。
从中获得价值?我们每周发布一篇关于AI工具、工作流和实用安全指南的深度文章。加入最先获得内容的读者 →
错误3:表单或API路由中没有输入验证
发生方式:AI生成接受任何输入的表单和信任任何传入数据的API路由。表单在HTML中有"required"属性,但没有服务器端验证。某人可以完全绕过表单,直接发送API请求并使用任何他们想要的负载。
为什么危险:没有服务器端验证,攻击者可以将脚本注入你的数据库(存储型XSS)、发送导致服务器崩溃的超大负载,或提交破坏你的应用逻辑的数据(如负价格或包含SQL的电子邮件字段)。
如何识别:打开代码库中的任何API路由或服务器操作。如果它使用req.body或表单数据而不检查每个字段的形状、类型和长度,你就有这个问题。
修复方法:使用模式验证库为每个端点添加服务器端验证。对于TypeScript项目,Zod是标准工具:
import { z } from 'zod';
const taskSchema = z.object({
title: z.string().min(1).max(200),
description: z.string().max(2000).optional(),
priority: z.enum(['low', 'medium', 'high']),
});
// In your API route:
const parsed = taskSchema.safeParse(req.body);
if (!parsed.success) {
return Response.json({ error: parsed.error }, { status: 400 });
}
对于任何被渲染为HTML的字段(评论、描述、个人简介),在显示前还应使用DOMPurify清理输出。
修复时间:30-60分钟。
错误4:API端点上没有速率限制
发生方式:AI永远不会添加速率限制,除非你明确要求。你的应用公开的每个API路由都可以被任何有脚本的人每秒hit数千次。
为什么危险:没有速率限制,某人可以暴力破解你的登录端点、通过重复hit列表端点来爬取你的数据库、压倒你的服务器(拒绝服务)或烧掉你的API配额(如果你的端点调用OpenAI或Stripe等外部服务)。
如何识别:如果你的任何API路由都不检查单个IP或用户最近发出了多少请求,你就没有速率限制。
修复方法:对于Vercel托管的应用,最简单的方法是开发环境使用内存速率限制器,生产环境使用基于Redis的限制器。Vercel的Edge中间件可以处理基本的速率限制。Upstash Redis(免费层)与@upstash/ratelimit用少量代码就能提供生产级别的速率限制。
合理的起点:已认证用户每分钟60个请求,未认证用户每分钟20个请求,登录/注册端点每分钟5个请求(防止暴力破解)。
修复时间:20-45分钟。
错误5:受保护页面和API上缺少身份验证检查
发生方式:AI生成了一个漂亮的仪表板页面和返回用户数据的API路由,但没有添加中间件来验证用户是否真的已登录。该页面"有效"是因为在开发期间你总是已登录的。在生产中,某人可以直接访问仪表板URL而无需登录,或hit该API端点并获得数据返回。
为什么危险:对受保护页面的未认证访问意味着任何人只需猜测URL就可以查看用户仪表板、管理面板或私有数据。未保护的API路由意味着任何工具(如Postman或curl)都可以不使用凭证拉取数据。
如何识别:打开隐身浏览器窗口(未登录)并直接导航到你的仪表板、设置或管理员URL。如果你可以看到任何内容而不被重定向到登录页面,你就有这个问题。然后尝试直接hit你的API路由——如果它们在没有有效会话cookie或auth令牌的情况下返回数据,那些是未保护的。
修复方法:添加在每个受保护路由之前运行的身份验证中间件。在Next.js App Router中,在你的项目根目录创建一个middleware.ts:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const session = request.cookies.get('session');
if (!session) {
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/dashboard/:path*', '/settings/:path*', '/api/protected/:path*'],
};
调整matcher来覆盖每个应该需要身份验证的路由。实现后在隐身模式下测试。
修复时间:15-30分钟。
如何在未来项目中防止这些问题
模式很清楚:AI生成在功能上有效但跳过安全的代码,因为你没有要求它。修复方法是首先要求它。
将以下内容添加到你的任何氛围编码项目的初始提示末尾:
SECURITY REQUIREMENTS:
- All secrets in environment variables (never hardcoded)
- Supabase RLS enabled on all tables with per-user policies
- Server-side input validation on every API route (use Zod)
- Rate limiting on all public endpoints
- Authentication middleware on all protected routes
- No service role key in client-side code
这不会捕获所有东西,但它会消除第一遍中五个最常见的漏洞,而不是需要稍后进行清理。
如果你想更擅长从一开始就编写能产生更安全代码的提示,我们的免费提示优化器可以帮助你组织你的说明。若要获得完整的安全演练,请参阅我们的分步指南:如何在将氛围编码的应用提供给客户之前保护它。
这是我们每周做的。关于AI工具、工作流和诚实观点的深度文章——没有炒作,没有填充物。加入我们 →
披露:本文中的某些链接是联盟链接。我们只推荐我们亲自测试和定期使用的工具。查看我们的完整披露政策。