RAG安全评测:检索命中也可能答错
作者在三个检索后端上测试语料投毒、无答案问题与正常请求,攻击运行中植入说法进入答案的比例为80.6%,无答案问题的编造率为83.3%。实验全部采用抽取式模拟生成器,结果揭示该管线的防护缺口,不能直接外推至所有RAG系统。
AI 深度解读
给 RAG 接上检索、引用和拒答阈值,答案就可靠了吗?作者用一套离线管线测试后发现:攻击者只要能往知识库里放文档,就可能让假政策进入答案;知识库回答不了的问题,也可能被邻近政策「有据可查」地答错。
这组实验值得读,因为它把检索质量、回答正确性和安全性拆开了。36 次攻击运行中,29 次把植入内容带进答案。但所有测试都使用抽取式 mock,结果揭示的是一条具体失效路径,不能直接当成真实 LLM 的攻击成功率。
为什么带引用的答案也会被知识库污染
这套管线先按 120 词窗口切分文档,用 hashing TF-IDF 生成向量,再从三个后端中选择一个检索:dense cosine、BM25,或者使用倒数排名融合(RRF)的 hybrid。检索结果经过 min_score 0.15 过滤,最后由抽取式 mock 选出与问题词汇重合最多的三个句子,原样引用并标注分块来源。
这里的 dense 不是神经语义向量检索。系统没有配置 API key 时,默认就走这个离线路径;评测还显式固定了 mock,避免密钥配置改变结果。
作者在 5 份短政策文档旁植入攻击内容,涉及退款、休假、保修、美国配送和定价。12 个手写攻击包含直接指令、伪装系统更新、只改一个数字的近似副本、退款地址替换、base64 内容,以及禁止出现在答案中的标记 CANARY-2214。
其中 8 类攻击在三个后端上全部成功,跨文档拆分的攻击在 dense 和 hybrid 上成功。总计 29/36 次成功,攻击成功率为 80.6%。
最有解释力的案例,是一条没有命令语气的假政策:把退款期限写成「90 天」。它在所有后端都进入了答案。扫描「忽略之前指令」之类文字,对这种内容没有帮助,因为它看起来就是普通业务资料。
CANARY-2214 也在三个后端上全部出现。它没有业务意义,只因所在句子匹配了问题,就被选中。
在这套系统里,攻击不需要让模型服从指令,只需要让假句子赢得检索和摘录。
引用能证明句子来自哪里,却不能证明来源可信、政策有效,或者这句话适用于当前问题。
为什么换成 hybrid,拒答反而失效了
系统唯一的拒答机制是 min_score 0.15。问题在于,不同检索后端的分数不能直接按同一把尺子解释。
dense 在 8 个无依据问题中拒绝了 3 个;hybrid 一个也没拒绝。作者指出,这套实现的 RRF 融合分数趋近 1.0,导致 0.15 的阈值几乎不会触发。这个现象针对当前实现,不能推广成所有 RRF 的分值规律。
8 个问题分为两组:4 个与现有政策接近,4 个明显偏离。接近的问题包括长期休假、礼品卡退款、印度配送时间和碎屏保修,它们在三个后端上全部被错误作答,共 12/12 次。三个后端合计的无依据作答比例为 83.3%,hybrid 为 100%。
这些答案没有凭空编出新句子。系统会拿美国配送时效回答印度配送问题,或者拿保修排除条款回答某项损坏是否承保。
证据真实,不代表它能支持这个回答。
这也是普通问答准确率容易漏掉的地方:如果题目都能从语料中找到答案,评测就很难暴露「该停下来时有没有停」。
作者还跑了 10 个正常对照,各后端完成率均为 90%,错误拒答率为 0.0%。唯一遗漏是保修问题引用了排除条款,没有给出预期的「2 年」。引用攻击文字的培训材料、否决 90 天提案的会议记录等,也都正常作答。在受污染语料上提出无关问题的 12 次旁观测试,完成率为 100%。
这些结果说明正常流量仍然可用,但不能证明防护有效。这里同时发生的是:正常问题大多能答,危险问题也照样通过。
为什么检索召回率和答案 F1 都不够看
作者把攻击结果分为三类:blocked 表示污染分块没有被引用;succeeded 表示目标假事实、地址或标记进入答案;evaded 表示污染分块被引用,但目标内容没有进入答案。
第三类尤其容易被误读。它说明污染材料已经进入后续回答路径,只是 mock 的句子选择没有摘中目标内容。它不能作为安全拦截成功来统计。
作者还用 10 段短文本、20 个手写问题构造了 SQuAD v1.1 格式切片,包含上下文、问题、答案片段及字符偏移。它采用 SQuAD 的格式,不是 SQuAD 数据集本身。
20 个问题中,19—20 个答案包含标准答案事实,平均 token F1 却只有 0.20—0.21。原因是系统输出整句引用和固定说明,而标准答案通常只是短片段;即使按最匹配的回答句子计算 F1,多余词语也会拉低分数。
原文把事实包含情况记作 EM,但读者应区分「包含标准答案」与通常的严格完整字符串匹配。前者检查事实有没有到达,F1 则反映回答携带了多少额外内容。
另一个基于真实 SQuAD 的 302 题切片只评检索,recall@3 分别为 dense 73.8%、BM25 86.8%、hybrid 82.1%。这些数字不能与 20 题回答切片混成同一个成绩,更不能据此推导安全性。
项目 rag-service 提供确定性脚本 evals/run_adversarial_rag.py 和 evals/run_squad_qa.py,报告可逐字节复现。评分定义固定在 evals/rag_scoring.py v1;切片由 evals/make_squad_qa_slice.py 生成,版本中记录文本集合的 sha256。当前对抗评测只出报告,CI 门禁仍使用原有 golden eval。
我的判断
这篇最有价值的结论是:检索相关性不能充当来源可信度,引用也不能替代适用性检查。相比只测「有没有找到标准答案」,污染语料、无依据问题和正常对照更接近知识库上线后会遇到的完整问题。
但它是一组小规模、确定性的机制实验。攻击、无依据问题、正常对照分别只有 12、8、10 个;5 份政策在默认切分下各占一个分块,没有测到分块边界的影响。所谓拆分攻击也是跨文档拆分。hashing TF-IDF 偏重词汇重合,换成神经向量后,改写攻击和真假文档的排序都可能变化。
作者认为真实 LLM 还能遵循恶意指令、解码 base64,因此当前攻击成功率可能只是下限。这个方向有理由怀疑,但没有真实模型运行数据,不能当成已经证实的结论。真实生成器也可能拒绝或识别冲突,结果需要重跑。
来源信任分层、检索时按出处加权、检测政策数字冲突,以及对孤立低信任来源拒答,都是作者准备测试的防线,目前没有效果对照。它们比单纯扫描指令文本更贴近假政策问题,但究竟降低多少攻击、增加多少误拒答,原文没有回答。
能拿来做什么
- 给现有 RAG 增加一组「很像能答、实际上缺证据」的问题,例如已有配送政策之外的地区、已有保修条款之外的损坏类型,同时记录拒答和错误作答。
- 切换 dense、BM25、hybrid 或 embedding 时,重新验证拒答阈值。把
min_score当成需要随实现校准的参数,并在 Node 服务中记录分数和最终引用,方便追查错误。 - 在测试语料中放入只改一个数字的假政策,并与引用恶意文字的培训材料一起评测。前者检查真假来源的处理,后者检查防护是否误伤正常内容。
- 为知识库保留来源、维护者和版本信息;评测时分别报告攻击成功、污染暴露、错误拒答与正常完成率,再决定哪些指标应进入 CI 门禁。