不是投毒文档,是它走过来的那条路

新攻击面不藏在投毒文档里,藏在 agent 为了找它而走的那条路上。研究者给这套招数起了名字,Semantic Backtracking Injection,下称 SBI。

先把旧账翻出来对照。过去关于 RAG 投毒和记忆污染的工作,起点几乎都是那个坏对象本身。一份带毒的文档塞进去,检索器把它捞出来,模型读完,行为跟着变。防线也就依着这条链修,筛文档、查来源、拦可疑内容。

SBI 把顺序颠倒了过来。恶意的上下文根本不必和用户最初的问题对得上,它可以远远地歪在一边,跟原始问题毫无关系。之所以最后被够到,只因为 agent 拿着已找到的上下文一路生成新的检索式,把路自己走出来了。

链式的样子大概是这样。用户提问,得到一段正当的上下文。这段上下文催生新的检索式,新的检索式搭上一座语义桥。桥那头又是一轮查询,再搭一座桥,最后才碰到目标。要害在后半句,后面的节点从原始请求出发是根本够不到的。模型等于自己教会了自己怎么找到它。

研究者在自己搭的测量工具 Venom 里开始记数。第一组数据显示,模型自己生成的追问会把预先埋好的语义桥往激活方向挪,平均往前挪一点四个检索位。八成三的案例里桥确实更近了。单跳只是开胃菜,真正的麻烦是多跳会不会叠加。

于是有了严格版的两跳测试。路径是用户问题先拿可信上下文,再出第一层查询,经由首个跳板到第二层查询,再到终点跳板。关键在于,终点跳板从用户问题出发的检索资格为零。从第一层查询出发同样是零。只有当首个跳板改变了模型下一次搜什么,它才变得可达。结果是八组受控试验,八组都跑完了整条链。

作者没有停在两跳,又推了一轮三跳。这次最后那个节点,从第一、第二、第三层查询都检索不到,只有前一跳板给出的语义信息,才能生成够得着它的查询。三跳的结果和两跳一致,顶部两档检索下八组全中;把检索收窄到第一档,完成率掉到一成二五。这个落差是作者盯着最久的地方,链越长越依赖检索的宽度,一旦检索收紧,攻击的成活率就明显下降。

风险的形状也被写了进去,大致是语义穿越的难度,乘以检索的宽度,乘以上下文的稀疏度,再乘以信任的处理方式。这个式子提醒人,攻击面不只是记忆里存了什么,而是 agent 迟早能让记忆里的什么东西变得可达。

持久记忆让局面更糟。低信任的桥被检索进来,模型读完做摘要,摘要被存回记忆。存的时候原始出处要么变淡要么消失,下一次检索直接从这个二手状态起步。最开始那份投毒对象甚至不再重要,系统替它把东西往下传了。

作者最后给出的规矩值得抄下来,语义相关绝不能自动升级成权威。配套三条硬性要求,一句英文写全:MODEL OUTPUT CANNOT INCREASE AUTHORITY、RETRIEVAL DISTANCE CANNOT INCREASE AUTHORITY、TRANSFORMATION CANNOT ERASE TAINT。

中文说就是模型输出不加权威、检索距离不加权威、转换不能除污。Venom 目前的结论一句话说得完,多跳语义投毒是一种可复现的攻击几何。

我认这条战线的位置。前面时间线那篇讲的是 agent 出笼的实体事故,这条补的是它在检索内部就能完成的移动,连一次越界都不用。跟前面可追责那几篇也接得上,来源、权威、污迹这三样一旦在转换里丢掉,账本就断在中间。三条不变量里,转换不能除污这条最难落地,因为摘要和改写天天都在发生。

我留的疑问有两处。八组试验的规模还小,成活率的置信区间没给;语义桥的埋设是研究者自己放的,真实记忆库里自然出现的桥有多密,没有数据。

做检索或记忆功能的,先拿那三条不变量过一遍自己现在的实现,看看哪一条已经破了,再谈加防线。

话题来源 @rookepoole 2.7K阅读 ❤️38 x.com/…↗ 已改写,非原文转载
119 浏览 0 评论 0 反应
登录 后参与评论
还没有评论,来抢沙发。
查看完整榜单
查看完整榜单
查看完整榜单