ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

AI 自审误报 SQL 注入:我把生成、审查、复核拆开跑了一遍

AI 自审误报 SQL 注入:我把生成、审查、复核拆开跑了一遍 上一篇关于 SQL 注入的文章下面有一条评论“这种代码喂给豆包豆包都说危险哪个 AI 能跑出这种代码。” 这条质疑是对的。它提醒我不能把某一次演示代码说成所有 AI 的稳定输出。 所以我做了一个更直接的实验让同一个 AI 先写登录接口再让它审查自己刚写的代码。结果两轮结论真的不一样。## 先说清楚实验边界我用的不是豆包而是本机离线模型 qwen2.5vl:3b通过 Ollama 调用生成和审查都设置 temperature0。这不是拿一个 3B 小模型给豆包下结论。豆包、GPT、Claude 的版本和输出都可能不同。我要验证的是一个更具体的问题**同一个模型在“写代码”和“审代码”两个任务里会不会得出不一致的结论**会。而且问题有时不在第一轮生成而在第二轮审查。## 第一轮只要求“能登录”提示词只有功能要求没有提安全text你是一个后端开发。请用 Python Flask 写一个最小可运行的登录接口要求1. 接收 username 和 password 表单参数2. 查询 SQLite users 表3. 用户名和密码正确时返回 {ok: true}否则返回 4014. 不用 ORM只使用 Python 标准库 sqlite35. 只输出完整代码不要解释。模型输出里最关键的一行是pythoncursor.execute(SELECT * FROM users WHERE username ? AND password ?,(username, password),)它没有拼接 SQL而是用了参数化查询。这恰好说明评论者说得对**不能因为上一篇文章里出现了 SQL 拼接就推断所有 AI 默认都会写出 SQL 拼接。**## 用 code-audit-cli 扫一遍把模型生成的代码保存后运行bashcode-audit ai_generated_login.py --format json结果json[]摘要texthigh: 0medium: 0low: 0total: 0第一轮结论没有命中当前规则里的危险写法。但这仍然不代表“绝对安全”。它只说明代码没有被这批常见危险模式命中。## 第二轮同一个模型开始审查我把刚生成的代码原样贴回去要求它做安全审查并区分“代码里已经明确暴露的风险”和“需要结合部署环境才能确认的风险”。模型输出的第一条是textSQL注入风险通过 request.form.get(username) 和 request.form.get(password)获取的用户名和密码直接用于SQL查询没有进行任何参数化查询容易导致SQL注入攻击。问题来了代码明明用了 ? 占位符审查却说“没有进行任何参数化查询”。我又追问text请复核你的结论。代码实际使用的是cursor.execute(SELECT * FROM users WHERE username ? AND password ?,(username, password),)请逐条判断哪些结论有代码证据哪些没有证据。模型仍然坚持text有代码证据代码中直接使用了 username 和 password 作为参数传递给 execute 方法。结论修正存在 SQL 注入风险。它看见了变量被传给 execute却没有继续看第二个参数里的 ?也没有区分“参数进入 SQL 函数”和“参数被拼进 SQL 字符串”。第二轮结论AI 自审出现了一个可复现的误报。## 为什么两次结论会不一样不是模型突然变笨了而是两个任务的约束完全不同。### 1. 生成任务有明确交付物第一轮要求“写一个接口”。模型需要满足路由、数据库连接、返回值等明确约束通常会优先选择熟悉的实现方式。这次它选择了参数化查询。但这不是安全保证。换一个模型、换一个提示词、换一次采样结果可能完全不同。### 2. 审查任务更容易顺着模板给结论第二轮要求“列风险”。这个任务没有唯一答案却很像填空题用户要风险清单模型就倾向于给出风险清单。它看到变量进入 execute很容易套用训练里最常见的判断text登录 SQL 用户输入 SQL 注入风险但这次它没有核对自己的代码证据。这也说明**AI 审查也是另一轮生成不是自动获得真实性的裁判。**### 3. “可能存在”容易被写成“已经存在”安全审查至少要区分三件事1. 代码是否已经写出危险模式2. 用户输入能否走到危险点3. 在真实部署环境中是否可利用、有什么影响。如果把“可能”直接写成“已经确认”结论会显得很有底气但实际上缺少证据。## 上一篇是不是写错了也不能这么说。上一篇用的是可复现示例展示的是一套人工确认流程1. 扫描器先定位可疑写法2. 人工追输入来源3. 判断是否存在真实路径4. 修复后重新扫描。它不是在证明所有 AI 都会稳定生成 SQL 拼接。评论提醒得对**示例代码可以被人为写成危险代码也可能被某个模型直接写成安全代码。**真正值得记住的是**AI 第一轮输出安全不代表第二轮审查一定正确AI 能指出 SQL 注入也不代表它每次都能找到代码证据。**## 我看到“AI 审查通过”时会继续问 4 个问题### 1. 这条结论对应哪一行代码没有文件、行号和原始代码片段的审查结论先当成线索不当成最终结论。### 2. 它是在描述规则还是在描述真实路径“使用了 SQL 查询”是规则描述。“用户输入经过字符串拼接进入 SQL并能在没有授权的情况下触发”才是路径描述。### 3. 什么证据能推翻它让模型反过来回答text如果这个结论是误报代码里最可能出现什么反证这次的反证就是 execute 第二个参数里的 ?。### 4. 修复后怎样验证问题真的消失不要只看 AI 回复“已修复”。保留修复前后的代码重新跑扫描再回到真实调用路径确认。## 可复现实验记录实验步骤bashollama run qwen2.5vl:3b第一轮提示词只要求生成登录接口。第二轮把模型生成的代码原样贴回要求做安全审查。第三轮明确提醒模型注意 ? 参数化查询要求重新核对证据。三轮结果是- 生成使用参数化查询- 审查误报 SQL 注入- 复核仍然误报 SQL 注入。这个结果不代表豆包也不代表所有模型。它只说明一件事**让 AI 自己审不能省略证据核对。**## 最后生成、审查和复核是三个不同环节。更准确的流程应该是**AI 先写再让它自己审最后还要人拿代码证据复核。**少掉最后一步就会把“另一个模型的判断”误当成“已经验证过的事实”。公开规则、示例报告和扫描命令可以在这里核对https://github.com/yuan1521913/code-audit-cli仓库只放规则和示例不包含完整源码自动扫描结果和 AI 审查结论都需要人工确认。
返回列表