最近常有人问我“哪个AI写代码厉害”,我的回答通常是一句反问:你打算怎么管它?代码生成速度再快,如果安全边界没立好,快反而是灾难。这几天我在团队里定了条规矩——AI生成的代码可以随便写,但提交前必须过安全检查。今天把这条规矩背后的思路拆开聊,顺便把实操中踩过的坑一起倒出来。
1. AI写得越快,越要先想清楚安全边界
1.1 代码生成速度和安全风险不是线性关系
AI写代码的能力提升是实打实的。以前写一套后端CRUD要俩小时,现在几分钟就能出一版能跑的。但速度上去了,一个被忽略的问题也会被放大:AI生成的代码并不天然安全,甚至因为它太会“模仿”,会把历史漏洞写法一并带进来。
我这段时间用AI编程的真实体验是,它特别擅长生成看起来“像那么回事”的代码。如果直接把它补全的登录逻辑、数据库查询、文件上传处理拿来用,表面跑得通,实际上可能藏着SQL注入、越权、不安全的反序列化等问题。原因不复杂:模型训练数据里有大量公开代码,其中相当一部分本身就是存在漏洞的历史代码。AI不是安全专家,它只是在做概率生成,觉得某段代码“最像标准答案”就贴给你了。
打个生活化的比方:AI像跑得飞快的新手司机,速度越快,越需要方向盘和刹车。你连刹车都没装好就让它上高速,出事只是早晚问题。所以我给团队定的第一条规矩就是:AI写代码可以“接活”,但接活之前必须过安全关。这条规矩比任何工具都管用,因为它把人的责任拉回来了。
写代码之前,还要先定义什么叫“安全”。不同场景的安全基线完全不同:内部管理后台和公网API的风险要求不一样,原型demo和核心支付系统的标准更不是一个量级。我把项目分成三类:本地工具、内部系统、公网生产服务,每类对应不同的检查级别。公网服务至少要过认证、授权、输入校验、输出编码、加密传输、日志脱敏这几关。这条基线直接写进团队代码审查规范,AI生成的代码和人类写的代码一视同仁。
1.2 别把“AI辅助”当成“AI负责”
另一个常见误解是:觉得AI辅助写的代码,出了问题AI负责。这完全想反了。AI只是工具,签名提交的人是你,发布上线的人也是你。就算用OpenAI Codex这类工具来写代码,最终责任也一定在人这边。想清楚这一点,后面所有安全动作才不会变形。
这里要特别提一下提示词注入。AI编程过程通常是把需求、上下文、代码片段糅进提示词,如果某个上下文来自不可信网页或用户输入,AI就可能被带偏。我曾经在一个项目里把从网上复制的一段代码直接贴进提示词,结果AI基于这段代码生成新工具函数,顺手把用户输入拼进命令字符串。后来审查时才发现这是典型的命令注入风险。这个教训说明:喂给AI的内容,本身就是安全边界的一部分。
实操上,我现在坚持几条原则:敏感信息绝不直接进提示词,统一走环境变量;不可信的外部内容先做“摘要化”处理,让AI只看到脱敏后的描述;不用那些以“无限制”“无审核”为卖点的AI聊天工具,这类工具往往意味着更弱的安全防护和更不可控的数据流向。正规渠道的AI服务至少还有基本的内容过滤和访问控制,出了事还能追溯。
2. 把缰绳套在“输入”和“权限”上
2.1 给AI的上下文做隔离
AI编程的一个新挑战在于:它不只是补全几行代码,而是以AI Agent的形式去读你的仓库、执行命令、改文件、跑测试。权限越大,越要防着上下文被污染。
我说一个真实案例。团队里有人把生产环境的数据库报错信息直接粘给AI,让AI帮忙分析问题。那堆报错里包含表结构、字段名,甚至部分用户标识。虽然最后没有造成实际泄露,但这种习惯非常危险。正确的做法是给AI一个“干净现场”:只提供错误类型、复现步骤、脱敏后的日志,整个分析过程不要让原始敏感数据跨系统流动。
尤其是前端开发,写代码之前需要注意业务逻辑并不代表只关注逻辑,更要关注哪些数据会出现在界面上、哪些字段属于敏感字段。AI生成组件时常常把接口返回整坨塞进状态管理,看似方便,实则把多余的用户隐私暴露给了前端调试工具。我现在的做法是:让AI生成代码之前,先把“数据字典”贴给它,明确哪些字段禁止打印、禁止上送埋点。这等于在提示词阶段就给AI套了嘴套。
2.2 给AI的执行权限做减法
AI编程工具越做越“主动”,很多已经能直接执行终端命令。这种情况下,权限就成了最关键的缰绳。我的原则是最小权限:能读就不要给写,能跑白名单命令就不要放开所有shell,能在容器里跑就不要让它直接操作宿主机。
具体怎么落?我目前的配置是这样:AI开发环境单独用一套目录,不跟公司主仓库混在一起;需要AI执行命令时,通过配置文件只放行格式化、lint、单元测试这类低危命令;安装依赖、修改数据库结构、推送远程仓库这些动作,全部设为“需人工确认”。像Cursor、Codex CLI这类工具都支持自定义允许命令,花十分钟配置好,后面能省几个小时的返工。
有人担心限制太多会影响AI效率,我的经验是恰恰相反。权限边界清晰之后,AI在给定的范围内反而更敢干活,因为它不需要反复试探什么能做什么不能做。真正拖慢速度的,不是限制,而是AI把整个代码库改得面目全非后,你才发现它连node_modules都动了。权限这事儿,宁严勿松。
3. 代码审查:让AI代码过“能上线”这关
3.1 审查时盯住四个高风险区
把AI生成的代码当成实习生提交的PR来审,心态就对了。审查不是让你读每行代码,而是盯住四类高风险区:身份认证与越权、输入输出校验、敏感信息处理、依赖引入方式。
后端写代码时需要注意的点,在AI场景下尤其要放大来看。AI生成一个接口,很容易默认“登录用户就能访问”,但实际业务里往往是特定角色才能操作。我踩过最典型的一个坑是:AI生成的导出功能只校验了“已登录”,没有校验“管理员”,结果普通用户把全套客户数据导走了。从那以后,我在审查清单里加了一条硬性要求:所有涉及数据操作的功能,必须看到明确的角色判断。
输入输出校验也是重灾区。前端写代码之前需要注意业务逻辑,但AI往往把“前端校验”当成了“安全校验”,实际上前端校验只是体验优化,后端必须重复校验。我建议在审查时专门看后端接口有没有对参数类型、长度、范围做约束,有没有把HTML编码、URL编码这类输出编码做对。一句经验:AI写代码越快,review越要慢,越要只看“边界”。
3.2 用工具辅助,但别把安全托付给“自动修”
现在有不少自动化工具能帮我们做安全测试:静态代码扫描、依赖漏洞扫描、密钥泄露扫描。这些工具确实能兜住一部分低级错误,但别指望它们替代人工审查。
我的工作流是三层叠加:第一层用Semgrep或CodeQL这类SAST工具扫规则,比如未授权访问、危险函数、不安全的反序列化;第二层用依赖扫描工具看第三方库有没有已知漏洞;第三层用Gitleaks之类的工具扫密钥和Token。跑完之后,每一处报告都必须人工确认。因为自动扫描经常报误报,也经常漏掉业务逻辑层面的漏洞。
更危险的是“自动修复”。AI自己修漏洞,往往只是修了个表面。举个例子:扫描报告说某处存在SQL注入风险,AI自动修复时给输入加了个转义函数,但底层的拼接SQL逻辑没改,等于把“裸奔”变成了“贴创可贴”。参数化查询、预编译语句、ORM绑定参数,这些才是根治手段。人必须看懂问题本质,再决定接受AI的修复还是自己重写。安全这条线,最终还是要靠人脑踩刹车。
4. 依赖、配置和部署里的隐藏雷区
4.1 依赖供应链:AI最爱“引包”,你要最狠“锁包”
AI生成代码时有一个让安全人头皮发麻的习惯:特别喜欢随手引入第三方包。你可能只让它写个日期格式化函数,它给你装了个完整的工具库。如果它选了一个维护者都跑路的包,或者一个名字和官方包高度相似的山寨包,供应链攻击就来了。
所以依赖这块,我要求团队做到“三锁”:锁版本、锁来源、锁许可证。前端用npm就锁package-lock.json,后端用Python就锁poetry.lock或pipfile.lock,Go项目锁go.sum。锁文件必须提交进仓库,任何依赖升级都要单独走审查流程。宁可多花十分钟确认这个包有没有人在维护、有没有高危漏洞,也不要让AI替你决定“该不该引进”。
配置管理也有讲究。之前提到过安全配置管理器,我用它把数据库连接串、API密钥、加密盐统一放到受控的配置中心,而不是散落在代码仓库。AI生成代码时就不需要在配置文件里写任何真实密钥,只需要一个本地开发用的占位符。这样做还有一个额外好处:即便AI生成的代码被公开,攻击者也拿不到生产环境的凭据。
4.2 前后端框架的安全默认值,必须手动确认
很多主流框架默认就带了一些防护,但AI生成的代码经常会“绕过去”。典型例子是CORS配置,AI为了让“跨域调试方便”,可能直接把Access-Control-Allow-Origin设成星号;再比如生成文件上传接口时,只校验扩展名,没校验文件内容类型,攻击者上传一个伪装成jpg的脚本就能拿到执行权。
框架自带的安全特性也需要主动开启。像Django默认有CSRF保护,但如果AI生成视图时用了@csrf_exempt,这条防线就没了;Spring Security也一样,AI生成的匿名接口一多,认证体系就形同虚设。我每次在审查时都会做一次“默认值核对”:这个框架默认开了哪些防护,AI有没有显式关掉?CSRF、HSTS、CSP、安全Header,一项项过。
部署阶段也有一套固定动作:容器不要用root用户跑,镜像用最小基础镜像,关闭调试端口,云安全组只放行业务需要的端口。这些细节AI不会替你记住,它只会给你“docker run -p 8080:8080”这种看似合理的命令。安全是最后一公里,越到上线越要盯紧。
4.3 本地跑大模型写代码,也别松安全弦
有人喜欢在本地用P104这类消费级显卡跑开源大模型来写代码,觉得数据不出内网,绝对安全。这个思路对了一半:数据确实没出公司,但模型本身、训练数据、推理框架的安全问题同样存在。
首先是模型来源。从不可信渠道下载的模型权重可能被人做过手脚,会在特定提示词下输出恶意代码。我建议只用官方发布、带哈希校验的权重包。其次是推理环境的依赖,本地跑模型通常会装一堆AI框架库,这些库同样有漏洞风险,要跟生产依赖一样定期扫描。最后是权限分离:即便模型在本地跑,也不要让它直连生产数据库,一切操作仍然走最小权限。本地部署不是免罪金牌,只是把安全边界从云端挪到了你的电脑上。
5. 实测踩坑记录:这些问题我都遇到过
5.1 AI“修”完漏洞,越修越漏
有次静态扫描报了三个高危漏洞,我把报告甩给AI,让它“修一下”。它改了半个小时,提交回来的代码里,两个问题确实是解决了,但第三个不仅没修好,还引入了新问题:它把原本的输入校验逻辑删了,改成了一个看起来更“严谨”的加密方式,结果直接把正常用户的登录流程搞挂了。
排查过程是这样的:先看diff,确认改动范围;再把扫描结果里的漏洞代码路径找出来;最后写一个针对性测试来验证修复是否生效。这个习惯我沿用至今——任何AI的修复都必须带着测试去验证,不能只看“代码不再报错”就认为安全了。另外,很多扫描工具会缓存历史报告,AI改完之后要重新跑一遍完整扫描,别拿旧报告当结论。
5.2 环境变量与密钥文件,差点被提交进仓库
那次是AI帮我初始化项目,它在.gitignore里漏写了.env,幸好提交前被代码审查发现。如果这个仓库是公开的,数据库密码、第三方API密钥就全都裸奔了。后来我强制在CI里加了一个“密钥扫描”步骤,只要有人把类似AKIA开头的密钥或私钥片段写进代码,构建直接失败。
这个坑提醒我两件事:第一,所有敏感信息和配置必须用环境变量或配置中心管理,不要相信“这个仓库是私有的”这种话;第二,密钥一旦疑似泄露,第一时间轮换,别想着“先观察一下”。就为这几秒钟的犹豫,很多公司吃过血泪教训。我现在会定期检查仓库的提交历史和Reclone记录,确保没有历史残留的密钥。
5.3 被安全防护拦截?先检查你的自动化行为
还有一次是测试脚本被网站安全防护拦了,页面弹出了那句经典提示:“本网站使用安全服务防护恶意自动程序。在验证您不是自动程序期间,将显示此页面。”第一反应是别急着关防护,而是检查自己的自动化程序是不是行为太像攻击了:高频请求、异常Headers、缺少验证Token。把请求频率降下来、配置好Cookie和Referer之后,问题就解决了。
这条经验放到AI编程上也成立。AI生成爬虫或自动化脚本时,经常不考虑目标服务的访问策略,很容易触发防护机制。写这类代码之前,先想清楚:对方允不允许你这样访问?有没有更友好的接口?如果你自己都过不了安全验证,那说明代码的行为边界有问题,不是网站的问题。
6. 可直接抄的AI安全自检清单
6.1 上线前十分钟过一遍这张表
下面这张表是我现在团队每次提交AI生成代码时必过的项目,你可以直接复制改成自己的版本。
| 检查项 | 要点 | 状态 |
|---|---|---|
| 提示词安全 | 是否包含密钥、Token、真实用户数据? | [ ] |
| 上下文隔离 | AI是否接触过不可信网页/用户输入,是否被提示词注入? | [ ] |
| 权限范围 | AI执行过哪些命令?是否在白名单内? | [ ] |
| 认证与授权 | 关键接口是否有角色判断?是否存在越权风险? | [ ] |
| 输入校验 | 后端是否重复校验参数?有没有拼接SQL/命令的可能? | [ ] |
| 依赖来源 | 是否使用锁文件?新增依赖是否经过来源和漏洞审查? | [ ] |
| 密钥管理 | 仓库中是否有.env、私钥、明文密码? | [ ] |
| 扫描结果 | SAST/依赖扫描/密钥扫描是否重新跑过并逐个确认? | [ ] |
| 框架默认值 | CSRF、CORS、HSTS、上传限制等是否保持安全默认? | [ ] |
| 部署配置 | 是否非root运行?调试端口是否关闭?安全组是否最小开放? | [ ] |
这套清单看起来繁琐,但真正熟练后十分钟内能过完。它最大的价值不是发现所有漏洞,而是强迫你把“安全”从抽象口号变成一个个可勾选的行动项。没有清单的时候,AI生成的代码特别容易“看起来很安全”,有了清单,你至少能回答自己:我为什么觉得它能上线。
6.2 常见问题速查表
这里再整理一份我在群里回答过很多次的问题速查表,基本覆盖了AI编程安全最常见的疑惑。
| 现象 | 可能原因 | 解决办法 |
|---|---|---|
| AI生成的代码被扫描报高危险漏洞 | 训练数据里包含漏洞模式 | 先定位漏洞根因,别急着让AI自修 |
| AI补全功能失效,比如VSCode写C没有代码提示 | 插件索引未完成或语言服务未启动 | 重建索引、重启语言服务,确认扩展与AI插件兼容 |
| AI建议把密钥放进配置文件 | 模型不了解你的部署规范 | 用安全配置管理器/环境变量集中管理凭据 |
| 爬虫脚本被网站安全防护拦截 | 请求频率或Header异常 | 降低频率、补齐请求头、遵守目标站点规则 |
| 依赖扫描报告出知名漏洞 | 引入了未锁版本的第三方包 | 升级并锁定版本,最好启用自动安全补丁流程 |
| 使用来路不明的“AI写代码神器” | 工具本身可能搜集代码和数据 | 停用不可控工具,改用有明确隐私政策的服务 |
这份表有个中心思想:AI编程的安全问题,大多数不是“AI很蠢”,而是“人忘了设边界”。代码生成得越快,边界就越应该提前画好。与其等漏洞爆了再排查,不如在提示词里、权限配置里、代码审查里,先把缰绳套上。
我在实际项目中体会到,给AI套上这些安全缰绳之后,团队迭代速度不但没变慢,反而更快了。因为大家不再担心AI埋雷,敢放手让它写;而每次审查出的问题,又会沉淀成新的检查项,反过来让提示词越来越精准。如果你今天还没给AI编程立规矩,我建议先做三件事:第一条,敏感信息禁入提示词;第二条,AI权限做成最小化;第三条,所有AI代码必须过一遍清单再合并。这三条先跑起来,后面再慢慢细化。