我差点把AI代码漏洞上线,有哪些教训可以避免重蹈覆辙?
摘要:三周前,我差点在生产环境搞出一个安全事故。 起因很简单:让Cursor写了一个文件上传接口,跑了一下,没报错,直接提交了。 结果被同事review的时候揪出来:AI生成的代码 String savePath = uploadDir
三周前,我差点在生产环境搞出一个安全事故。
起因很简单:让Cursor写了一个文件上传接口,跑了一下,没报错,直接提交了。
结果被同事review的时候揪出来:
// AI生成的代码
String savePath = uploadDir + fileName; // fileName来自用户输入
File file = new File(savePath);
file.transferFrom(channel);
fileName是用户传进来的,如果传../../etc/passwd,文件就写到服务器根目录去了。
这是一个经典的路径穿越漏洞。
功能完全正常,测试全部通过,但任何一个懂安全的人看一眼就知道这是定时炸弹。
那天之后,我把过去3个月用Cursor踩过的坑,全部整理了一遍。
一共10个。每一个都是真实交过的学费。
第一组:认知层的坑
这组坑最普遍。几乎每个刚开始用AI编程工具的人都会踩。
坑1:把Cursor当"更好的补全"在用
我最开始的用法是这样的:
写几个字 → 等AI补全 → 不满意就删 → 重写
用了两周,感觉"也就那样",效率提升有限,还经常被AI的补全打断思路。
后来才明白:这个用法完全用错了方向。
Cursor的核心能力不是补全,是生成。
正确的用法是:
描述清楚需求 → AI生成完整代码块 → 我来review和调整
两种用法的效率差距,不是10%,是10倍。
一句话改法: 不要等AI补全,要主动用Ctrl+K描述需求,让AI一次生成完整的函数或模块。
坑2:Prompt写得太模糊,然后怪AI不好用
这是我听到最多的抱怨:
"AI写的代码太烂了,还不如自己写。"
我每次听到这个,都想问一句:你的Prompt写的是什么?
模糊Prompt:
写一个登录接口
AI生成的:
public String login(String username, String password) {
User user = userMapper.findByUsername(username);
if (user != null && user.getPassword().equals(password)) {
return "success";
}
return "fail";
}
密码明文比较,没有token,没有异常处理,没有日志。能跑,但没法用。
清楚的Prompt:
写一个用户登录接口,要求:
1. 用户名+密码登录,密码用BCrypt校验
2. 登录失败超过5次,锁定账户30分钟(用Redis存失败次数)
3. 登录成功返回JWT token,有效期7天
4. 记录登录日志:IP、User-Agent、时间、成功/失败
5. 异常统一用BusinessException抛出,返回Result<T>包装
6. 技术栈:Spring Boot 3, MyBatis-Plus, Redis
AI生成的: 80%可以直接用。
AI的质量上限,取决于你Prompt的质量上限。
一句话改法: 写Prompt之前,先想清楚如果让一个新同事来做这个功能,你会告诉他哪些信息。把这些信息全写进去。
坑3:以为AI"懂"你的项目
这个坑很隐蔽。
Cursor确实能读取你的项目文件,但它不知道你们团队的规范、你的代码风格、你的命名习惯。
结果就是:
// 你的项目规范
public class UserService implements IUserService { ... }
// 返回值统一用 Result<T>
// 异常统一用 BusinessException
// AI生成的(没有规范约束时)
public class UserServiceImpl implements UserService { ... }
// 直接返回实体类
// 用 RuntimeException 抛异常
每次生成完都要手动调整,改来改去,效率反而变低了。
