你让AI写个用户注册功能,它反手给你塞了段MD5哈希代码。不是SHA-256,不是bcrypt,是1992年诞生、2004年就被证明不安全的MD5。更诡异的是,这事我三周内撞见三次——不同开发者,不同项目,同一串危险代码。
正方:AI只是照本宣科
Cursor没发疯。它的行为完全符合训练数据的统计规律。
当你输入"implement user registration",模型做的不是"思考什么是最佳实践",而是模式匹配。它在数十亿token里找"password hash Node.js"最常见的共现组合,然后吐出答案。
问题在于数据来源的时间分布。2008到2019年间,StackOverflow答案、技术博客、GitHub片段里充斥着这样的代码:
「const hash = crypto.createHash('md5').update(password).digest('hex');」
这段模式出现了数百万次。bcrypt虽然2012年后就是正确答案,但存量内容被旧数据淹没。模型学到的"典型"解决方案,恰恰是过时的解决方案。
这不是模型架构缺陷,是训练语料的时间偏见。AI没有安全意识,只有频率意识。
反方:开发者不能甩锅给工具
但把责任全推给AI,等于承认开发者是代码的搬运工而非思考者。
原文作者提到,那位Node.js开发者"不是粗心"——但MD5用于密码存储是安全领域的常识性错误。CWE-328(使用损坏或有风险的加密哈希函数)在漏洞数据库里躺了十几年,任何生产环境代码审查都该拦截这类代码。
更隐蔽的风险在于:SHA-256看起来比MD5"现代",但同样错误。
SHA-256的设计目标是速度——每秒能在GPU上处理数十亿次哈希。这对文件完整性校验是优点,对密码存储是致命缺陷。攻击者用消费级显卡配合字典,破解SHA-256哈希的速度比MD5更快。
AI生成代码通过了"能跑"的测试,但没通过"该用吗"的审查。这个判断缺口,最终是人的责任。
技术拆解:为什么速度是敌人
密码哈希的核心矛盾在于:合法用户登录时需要快,攻击者暴力破解时需要慢。
MD5、SHA-1、SHA-256都是通用哈希函数,设计目标是高效计算。bcrypt和Argon2id则是有意"做慢"的算法——通过可配置的计算成本,让单次哈希耗时200-300毫秒。
对用户来说,登录多等0.3秒无感知。对攻击者来说,每秒尝试次数从数十亿骤降到个位数,字典攻击的经济成本变得不可承受。
原文给出的正确实现:
「const bcrypt = require('bcrypt');
const hash = await bcrypt.hash(password, 12);」
12轮是2012年后的推荐下限。OWASP目前的首选是Argon2id,内存硬型设计能抵抗GPU/ASIC专用硬件攻击:
「const argon2 = require('argon2');
const hash = await argon2.hash(password);」
Python同理:
「import bcrypt
hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))」
我的判断:这是AI辅助编程的结构性痛点
这件事的重要性不在于"AI会写烂代码"——人类写的烂代码更多。关键在于AI输出的"平均质量"陷阱。
Cursor生成的是训练数据里的最常见解,而非当前最佳实践。在技术领域,这两者往往存在时间差:旧方案传播更广,新方案更安全。当AI成为主要编码工具,这种滞后会被批量复制到无数新项目。
更麻烦的是反馈循环。如果今天的AI生成MD5代码被大量采纳,明天的训练数据里MD5出现频率更高,模型更难摆脱这个模式。
短期应对很朴素:关键安全代码必须人工复核,不能把AI输出直接塞进生产环境。长期则需要训练数据的时间加权策略——让2019年后的安全实践获得更高采样权重,或者显式注入"当前推荐"的知识层。
否则我们会持续收到2026年的MD5密码库,像某种技术考古的黑色幽默。
热门跟贴