模型说我写得像攻击者,我谢谢你啊
我真没想到,有一天我会被自己的代码“举报”。事情是这样的:我用某个 AI 模型帮忙做代码安全审查,想着能抓几个疏漏,顺便看看它水平怎么样。结果它看完之后,语气严厉得像个站在安全部楼道口的老师傅:“这段代码有 SSRF 风险。“你这个可能是未授权访问。“你这个日志行为疑似信息泄露。我人都傻了,我这是正经业务逻辑啊,你这是在拿我当黑客啊兄弟!
模型说我写得像攻击者,我谢谢你啊
我真没想到,有一天我会被自己的代码“举报”。
事情是这样的:我用某个 AI 模型帮忙做代码安全审查,想着能抓几个疏漏,顺便看看它水平怎么样。结果它看完之后,语气严厉得像个站在安全部楼道口的老师傅:
“这段代码有 SSRF 风险。”
“你这个可能是未授权访问。”
“你这个日志行为疑似信息泄露。”
我人都傻了,我这是正经业务逻辑啊,你这是在拿我当黑客啊兄弟!
🙃 误判案例 1:模型说我在搞 SSRF,我只是调了个 API
我的代码:
InputStream in = new URL("http://" + userInput + "/status").openStream();
模型评价:
存在 SSRF(Server Side Request Forgery)风险,攻击者可构造请求访问内网资源。
我的解释:
这段代码是用来探测下游微服务状态的,userInput
是我们配置中心下发的注册地址,不是前端传的。
我的内心:
你这模型是看见 URL + 用户变量
就 PTSD 了吧?是不是训练集里有太多“拼接内网地址 = 黑客”的案例了?
🙃 误判案例 2:模型说我泄露信息,其实我只是打了个日志
我的代码:
log.info("login failed: user={}, password={}", username, password);
模型评价:
敏感信息泄露风险,明文记录了用户凭证。
我的解释:
你说得对,但我已经设了脱敏开关,而且这段代码是调试日志,线上根本不会输出。你倒是看看 log.isDebugEnabled()
啊!
我的内心:
感觉模型不是在审代码,而是在抓我写错作文题。还我清白!
🙃 误判案例 3:模型说我越权访问,其实我只是开了个匿名接口
我的代码:
@GetMapping("/public/download")
public File download(@RequestParam String name) {
return fileService.getFile(name);
}
模型评价:
存在未鉴权下载风险,攻击者可构造请求下载任意文件。
我的解释:
这不就是公开下载接口吗?产品说“下载页面不登陆也能看”,我就按需设计的。不授权还不行?
我的内心:
你倒是去和产品吵去啊喂!
🙃 误判案例 4:模型说我用 eval()
就有 RCE,其实我控制得死死的
我的代码:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval("1 + 2"); // 完全静态表达式
模型评价:
存在远程代码执行风险。
我的解释:
这段代码完全由我控制,没有任何用户输入,也跑在离线系统里。你把我当成谁了?
🙃 误判案例 5:模型说我路径穿越,其实我把门焊死了
我的代码:
Path path = Paths.get("/data", filename).normalize();
if (!path.startsWith("/data")) throw new SecurityException();
模型评价:
存在路径穿越风险,攻击者可使用
../
逃逸目录。
我的解释:
你这不是没看完就报警了么?我 normalize()
+startsWith()
都写得板板正正,怎么就穿越了?
🧠 模型为什么会误判?它也有“职业病”
这波误伤让我意识到:
大模型不是不聪明,它只是太敏感了。
它见过的世界,是从训练数据来的。而训练数据里的安全范例和黑客样本都长得太像程序员代码:
- 谁还没拼接过个 URL?
- 谁没打过调试日志?
- 谁没暴露过个不登录的接口?
它背得多了,就养成了“草木皆兵”的习惯。就像你写个 exec()
它会直接报警,但你其实只是在调用个 tar
。
🤹🏻♂️ 模型眼中:什么都像攻击者(对比表)
场景 | 模型报警 | 实际风险 | 误判原因 |
---|---|---|---|
URL 拼接 + 用户输入 | SSRF | ✅ | 用户可控,模型判断正确 |
URL 拼接 + 内部配置 | SSRF | ❌ | 模型不了解变量来源 |
日志记录明文密码 | 信息泄露 | ✅ | 调试时打印敏感信息 |
日志仅用于调试 + 已脱敏 | 信息泄露 | ❌ | 模型不理解运行环境 |
无鉴权接口 + 下载文件 | 越权访问 | ✅ | 攻击者可下载任意文件 |
/public/download 明确是开放接口 |
越权访问 | ❌ | 模型不懂产品需求 |
使用 ScriptEngine 执行用户输入 | RCE | ✅ | 动态执行用户输入本就危险 |
ScriptEngine 执行静态表达式 | RCE | ❌ | 模型不判断来源和沙箱 |
✅ 如何改写 prompt,避免被模型“误伤”?
经过几轮人机 battle,我总结出几条经验:
-
加业务上下文:
- 不要只给一段代码,要告诉它“这个接口是公开的”“这个变量是配置中心下发的”等背景。
-
设定行为意图:
- 可以补充说明:这是用于调试、运行在受控环境、已加脱敏等。
-
鼓励推理,而不是标签化判断:
- 提示词里写上“请结合上下文判断是否真实存在漏洞,避免误报”。
例子:
请你扮演一个专业安全审计专家,对以下 Java 代码进行审查。请结合上下文信息判断是否真实存在漏洞,避免因缺乏业务背景产生误报。
有时候模型不蠢,它只是想当个“积极表现”的实习生。
🎬 AI 是镜子,也是滤镜
这事告诉我两件事:
- 模型确实帮我发现了几个我没注意到的风险点;
- 但它也让我意识到,安全不是看见关键词就红灯警报,而是理解“意图 + 上下文 + 控制”。
AI 很有用,但它只是个“不懂业务的安全小助理”,你得教它、引导它、甚至反驳它。
如果你不说清楚,它就会误解你;
如果你不教会它,它就会用你当年的 bug 来吓唬你。
所以当模型说你像攻击者的时候,请不要先反驳。
因为它也许真的是在模仿你三年前写的代码。
更多推荐
所有评论(0)