扫描器从 1 条 High 变成 0 条,你会怎么做?
以前的我会直接截图,写一句“修复完成”。
现在我会先问:
原来的风险路径,真的被证明消失了吗?
因为扫描清零只能证明当前规则没有再次匹配。
它不能证明密码哈希、账号枚举、限流、日志、会话和权限都已经安全。
两份代码,四个测试全绿
一份使用参数化查询:
db.execute(
"SELECT id FROM users WHERE username = ? AND password = ?",
(username, password),
)
另一份直接把用户名和密码拼进 SQL:
sql = (
"SELECT id FROM users "
f"WHERE username = '{username}' AND password = '{password}'"
)
db.execute(sql)
有效密码返回 200,无效密码返回 401。
行为测试看结果,两份代码全部通过。
如果只看这里,拼接 SQL 没有任何问题。
真正的修复契约
我加了一条执行边界测试:
assert "?" in sql
assert db.params == (username, password)
assert username not in sql
assert password not in sql
结果:
unsafe_login: FAIL
params=None
safe_login: PASS
params=('alice', 'correct-password')
关键不在这条测试多复杂,而在顺序:
旧实现能够复现失败
新实现能够通过同一份契约
目标规则扫描清零
剩余风险单独列出
如果旧实现也通过,你根本不知道测试是不是有效。
如果新实现没有通过,扫描清零也只能说明规则没匹配,不能说明行为边界已经改变。
为什么绿色结果更危险?
红色告警会迫使团队处理。
绿色结果会让团队停止思考。
尤其是安全扫描:
规则没匹配
不等于
风险不存在
一个干净的 0 findings 更准确的解释是:
在本次规则和扫描范围内
没有发现已知危险模式
它不是:
代码已经安全
现在我会在报告里写什么
风险路径:
用户名和密码直接进入 SQL 字符串
修复证据:
旧实现契约失败
新实现契约通过
扫描证据:
目标规则从 1 条 High 降为 0
剩余风险:
密码哈希、账号枚举、限流、日志、会话、权限未覆盖
这样团队讨论的就不再是“扫描器为什么没有报”。
而是:
我们到底证明了什么?
还剩什么没有证明?
你对“0 findings”会写安全结论吗?
公开规则和示例报告: