做产品 PMaker
空格的键盘
AI 写代码又快又勤 —— 也把三类老毛病写得特别顺手 ① 密钥硬编码 把密钥、密码直接写进代码 随代码一起上传,等于公开 拦:密钥必须走环境变量 ② 越权访问 接口不校验「你是谁、能看什么」 登录了就能看别人的数据 拦:每个接口都查身份和范围 ③ 注入 把用户输入拼进查询或命令 一句话就能改你的查询逻辑 拦:参数化,不拼字符串 为什么 AI 特别容易留这类坑 它学的是「最常见写法」,而示例代码里密钥硬编码、不校验权限的写法特别多 AI 补全的代码 = 高速流水线上的半成品 —— 安全责任在你,不在工具

AI 不会故意留漏洞,但它会忠实地复刻它学到的「常见写法」——而常见写法里恰好全是这三类坑。

AI 代码的常见漏洞

用 AI 写代码,产量上去了,但有一件事不会自动变好:安全。AI 生成的代码里,翻来覆去就是那几类漏洞——而且它写得特别顺手。

你会遇到的现象
  • AI 生成的代码里,API 密钥就明晃晃写在配置里
  • 接口查了登录,没查权限——登录用户能看别人数据
  • 用户输入直接拼进了数据库查询

三类高频漏洞

① 密钥硬编码。把 API 密钥、数据库密码、签名密钥直接写进代码或提交到仓库。这是 AI 生成代码里最普遍的一类——因为示例代码、教学博客全是这么写的。一旦代码入库、上云,密钥等于公开,攻击者拿它做合法调用,账单还记在你头上。

② 越权访问。接口校验了「是否登录」,但没校验「能不能看这条数据」。用户 A 登录后能看用户 B 的订单、改用户 B 的资料。AI 生成的 CRUD 接口尤其容易漏这一层——它默认「登录了就放行」。

③ 注入。把用户输入直接拼进 SQL、命令、HTML。这是提示注入在代码世界的亲戚——本质一样:把「数据」当「指令」。AI 生成代码时常用字符串拼接,恰好是最危险的那种写法。

这三类有一个共同点:它们不是「高级漏洞」,而是基础安全习惯。工具不会替你养成习惯,它只会复制它见过最多的写法。

为什么 AI 特别容易犯

三个原因,都跟 AI 的工作方式有关:

一、学的是「常见写法」。AI 从海量代码里学「一般怎么写」。而公开代码里,密钥硬编码、不校验权限的示例比比皆是——它学到的「正常」恰好就是不安全的。你让它「写一个连接数据库的代码」,它默认带出硬编码密码。

二、只看到局部。AI 生成一段代码时,看不到你的权限系统、你的密钥管理、你的安全规范。它不知道环境变量叫什么,只好把密钥写进代码里先让功能跑通。

三、它追求「能跑」,不追求「安全」。生成的目标是完成任务、代码可运行。安全性是隐性的质量要求,除非你在提示词里明确要求,它不会主动加。

所以不要问「AI 为什么老写不安全代码」——问你自己为什么不审查。工具提速不等于质量提高,安全这条线本来就要人来守。

三个原因,都跟它的工作方式直接相关 学的是「常见写法」 公开代码里,硬编码密钥、 不校验权限的示例比比皆是 它学到的「正常」, 恰好就是不安全的 只看到局部 看不到你的权限系统、 密钥管理、安全规范 不知道环境变量叫什么, 只好把密钥写进代码 追求「能跑」 生成的目标是完成任务、 代码可运行 安全是隐性要求, 不明说它就不会加 最低成本的一层防线:在提示词里直接要求「密钥不硬编码、每个接口校验权限、用户输入全部参数化」。 这三类都不是「高级漏洞」,而是基础安全习惯——工具不会替你养成习惯,它只会复制它见过最多的写法。 所以别问「AI 为什么老写不安全代码」,问你自己为什么不审查。
量上来了不是放松审查的理由,恰恰是审查更不能省的理由。AI 代码要走和人工代码一样的评审、测试、扫描——AI 是流水线,你是质检。

排查清单

不管代码是 AI 写的还是人写的,上线前用这份清单过一遍:

一、扫描密钥。仓库里有没有硬编码的密钥、密码、Token?用扫描工具全局查一遍。密钥一律放环境变量或密钥管理系统。发现已提交的密钥,立刻吊销重发——只是删掉远远不够。

二、检查每个接口的权限。每个接口逐一问:有没有校验登录?有没有校验「当前用户对这条数据的访问权」?测试方法很简单——用 A 的会话访问 B 的资源,看拦不拦得住。

三、检查所有「拼」的地方。凡是用户输入(或任何外部输入)进入查询、命令、HTML 的地方,都要是参数化写法,而不是字符串拼接。

四、让 AI 自己先自查。生成代码时,在提示词里加一句:「写出符合安全规范的版本:密钥不硬编码、每个接口校验权限、用户输入全部参数化。」效果立竿见影。把安全要求写进提示词,是成本最低的一层防线。

五、让审查成为流程。AI 代码要走和人工代码一样的评审、测试、扫描。不要因为「代码量上来了」而放松审查——恰恰因为量上来了,审查更不能省。

最后记住:AI 是流水线,你是质检。流水线快,不代表产品合格。