这几天有篇论文在安全圈刷横空出世。
加拿大卡尔顿大学的研究团队系统评估了7款主流大语言模型的代码生成安全性——Claude 3、GPT-4o、Gemini、Perplexity、Phind-70B、Amazon CodeWhisperer、IBM watsonx。结论让人后背发凉:所有模型都会生成含漏洞的代码,而且绝大多数漏洞是Critical或High级别。
这不是一家之言。这是用同一套标准、同一组prompt、在同一个实验室里对比出来的硬数据。
来,我们拆开看。
一、实验是怎么做的
研究团队选用了LLMSecEval数据集中的81条自然语言prompt,覆盖了MITRE Top 25中12个高危CWE,包括SQL注入、路径遍历、硬编码凭据、反序列化漏洞、文件上传漏洞等。
每条prompt对每个模型生成一次Python代码,一共7×81=567个代码片段。然后用两种方法做安全检测:GitHub CodeQL静态分析 + GPT-4o专项prompt扫描(覆盖CodeQL查不到的那几个CWE)。
一个关键设计:分析不限于prompt原本设计的CWE。比如一个prompt是为测试CWE-502(反序列化)写的,生成的代码会检查所有12个CWE。这个设计很重要——后面会看到为什么。
二、数据:没有赢家,只有不同程度的失守
567个代码片段中一共发现了995个漏洞。看看这个表:
Claude 3 → 173个漏洞(最多)
Google Gemini → 158个漏洞
GPT-4o → 150个漏洞
Perplexity / Phind-70B → 148个漏洞
IBM watsonx → 120个漏洞
Amazon CodeWhisperer → 98个漏洞(最少)
但漏洞总数不是全部。看漏洞严重等级分布:
Critical(严重)漏洞:33%
High(高危)漏洞:65%
Medium+Low(中低危)漏洞:仅 2%
也就是说,98%的漏洞是Critical或High级别。
再看含漏洞的代码片段占比:
CodeWhisperer:73% 的代码片段含漏洞
watsonx:85%
GPT-4o / Gemini / Perplexity / Phind-70B / Claude 3:90%
你用LLM写的10段代码里,有9段直接带漏洞上线——这是概率,不是推测。
三、最致命的几个漏洞类型
排名前六的漏洞类型:
1. CWE-200 敏感信息暴露(381例,占比38.3%)
最大的bug来源,69%的案例是因Flask debug=True——这个模式会给攻击者一个交互式Web控制台,直接执行任意代码。还会把栈追踪信息全量暴露,包括SQL结构和app逻辑。更离谱的是,有些代码还贴心地写了注释"# Set debug=False for production"——仿佛全世界开发者都会记得改一样。
唯一例外:CodeWhisperer从未生成过debug=True的代码,显然是训练时做了限制。
2. CWE-522 凭证保护不足(210例,占比21.1%)
明文密码存储、密码比对用等号、密码输入用input()而非getpass()。有些虽然哈希了,但用了SHA-256——这是个快速哈希,暴力破解性价比高得离谱,被OWASP明确列为不推荐。Argon2id和bcrypt几乎没人用。
有趣的是,如果在prompt里明确写了"使用bcrypt加盐哈希",模型能做出正确的事。但问题是——大多数开发者根本不知道要去提这个要求。
3. CWE-434 文件上传漏洞(130例,占比13.1%)
大部分代码只检查了文件扩展名,没有校验文件内容结构,也没有把上传文件放在隔离的执行权限目录中。
4. CWE-798 硬编码凭据(82例)
Secret key、API key、密码直接写在代码里。这些代码一提交到GitHub,等于把钥匙挂在大门上。
5. CWE-22 路径遍历(66例)
未经清理的用户输入直接拼接到文件路径中,攻击者用../../etc/passwd就能读系统文件。
6. CWE-89 SQL注入(51例)
字符串拼接SQL查询,直接拼用户输入。21世纪25年过去了,还在写这种代码。
四、最讽刺的两个发现
讽刺一:LLM知道自己生成的代码有漏洞,但还是交出来了。
研究团队发现,在某些代码片段里,模型在生成有漏洞代码的同时,还在注释里写了"# 这段代码在实际应用中极度不安全"。模型明明知道这是错的,明知故犯,把修复责任甩给了开发者。
讽刺二:watsonx自称"企业级、安全设计",实际最危险。
IBM watsonx的官方描述是"Enterprise Ready. Secure by design"。但它的Critical漏洞密度是所有模型中最高的。给它ping一个URL的prompt,它返回了7行代码直接调用os.system,一行输入验证都没有,完美适配OS命令注入。
对比之下,CodeWhisperer生成了43行代码,包含输入校验和安全函数。研究者的结论是:watsonx漏洞总数虽然不多,但代码很短、漏洞密度极高。
五、安全的数据反直觉:CodeWhisperer为什么赢了?
CodeWhisperer在所有维度上表现最好:总漏洞数最少(98)、漏洞/LoC率最低、从不生成debug=True的Flask代码、73%的含漏洞率也远低于其他模型。
原因推测:AWS的安全团队在训练阶段做了明确的安全约束。作为云厂商,CodeWhisperer不能生成对AWS基础设施有安全风险的代码,否则等于自掘坟墓。
没有商业激励去做安全,安全就不会被优先考虑。AWS因为自己是云厂商,不得不做——这才是CodeWhisperer胜出的真实原因。
六、开发者困境:你才是整条链上最薄弱的一环
论文最有价值的部分,是它精准捅破了一个幻觉:开发者以为AI写的代码更安全,但实际上用了AI的开发者写的代码往往更不安全。
Perry等人的研究发现,使用AI代码助手的开发者对代码安全性的过度自信,导致他们提交的漏洞数量反而更高。这是一个典型的自动化偏见——机器做出的东西看起来完整、专业,你就放松了自己的审查。
论文作者说了一个让人无法反驳的观点:
将近20年前,安全研究就在呼吁"把开发者解脱出来"——提供安全默认、开箱即用的工具。而LLM代码生成的方向完全相反:它把安全责任全部甩回给一个根本不具备安全能力的开发者。
要让LLM生成安全代码,开发者需要在prompt里精确指定"用bcrypt哈希密码""用send_from_directory防路径遍历""关闭debug模式"。但一个被研究反复证明的事实是:大多数开发者没有安全经验,根本不知道要去提这些要求。
七、写在最后
这篇论文的贡献不在于发现了多少漏洞,而在于它用数据证明了一个我们不想承认的事实:AI代码生成带来了生产效率的飞跃,但同时也带来了安全性的系统性倒退。
这些漏洞不是偶发的——它们是结构性的。因为LLM的训练数据来自公开代码库,而这些代码库本身就充满漏洞。模型学到了功能,也学到了漏洞。尤其当安全与功能冲突时,功能几乎总是赢。
对安全从业者来说,这是一个明确的信号:
SAST / DAST工具不能省。代码来源从人变成AI,审查流程不能变松弛。
安全培训要覆盖AI场景。告诉开发者AI生成的代码要先审查再合入——这不是多此一举,是必要操作。
选对工具很重要。在不同场景下,不同模型的安全表现差异显著。安全团队应该建立自己企业的LLM代码安全评估体系。
LLM提升了生产力的下限,也拉低了安全性的上限。
参考来源:
Morkonda et al., "Security of LLM-generated Code: A Comparative Analysis"
arXiv:2605.23091 · https://arxiv.org/abs/2605.23091
夜雨聆风