我差点把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 抛异常 每次生成完都要手动调整,改来改去,效率反而变低了。
阅读全文