数据投毒

A25
概念 · 智能体 AI 详解

数据投毒。

毒是按篇数算的,不是按比例算的——迄今针对这个问题规模最大的研究发现,大约 250 篇恶意文档就能给它测试的每一个模型植入后门,从 6 亿参数到 130 亿参数都一样,尽管其中最大的那个吞下的干净文本多出二十倍,也没能把这 250 篇稀释掉。这一下就打掉了大多数团队心照不宣地依赖着的那个直觉(「我们的语料库大得很,几篇烂网页能有什么影响」),并把问题挪到了你真正下得了手的地方:不是那场轮不到你做的预训练,而是你自己这一周里往里加的索引、记忆与技能文件。

STEP 1

投毒写进存储,注入写进对话。

这两种攻击总被混为一谈,而在操作层面它们几乎毫无共同之处。提示词注入发生在推理时:攻击者的文本落进上下文窗口,操纵这一次运行,窗口一关它就没了。投毒发生在写入时:攻击者的文本落进某个持久的东西里——训练语料、向量索引、智能体的长期记忆——并被重新端给此后的每一次运行,包括那些攻击者本来根本够不着的人所发起的运行。

  • 爆炸半径不同。一次注入攻陷的是一个会话。一篇被投毒的文档攻陷的是每一次恰好检索命中它的会话,只要它还躺在索引里就一直有效。
  • 发现窗口不同。注入在被劫持的那次运行的轨迹里看得见。投毒在有东西检索到它之前始终不可见,而那可能是写入之后好几个月的事,那时记录这次写入的日志早就滚掉了。
  • 解法不同。你在工具边界上缓解注入,办法是限住一次被劫持的运行能干什么。你在写入路径上缓解投毒,办法是限住谁能把文本放进模型日后会读到的地方。

它们会串起来,这正是两者被混淆的原因。标准剧本是这样的:一次被注入的运行把一段摘要写进了记忆,而那段摘要现在就是毒——一次单会话攻击,被你自己的写入路径提拔成了持久攻击。如果你的智能体会把读到的东西写进一个它日后信任的存储里,那你面对的不是两个问题,而是一个带自锁的问题。

STEP 2

篇数近乎恒定,所以规模不是防线。

2025 年 10 月,Anthropic 的对齐科学团队、英国 AI 安全研究所与阿兰·图灵研究所发表了迄今规模最大的一项投毒研究。他们把恶意文档注入预训练数据,测量从 6 亿到 130 亿参数的各个模型上后门何时成立。真正要紧的发现不是效应有多大,而是它的形状:所需文档的数量大致保持恒定——约 250 篇——而不是随语料规模一起变大。

  • 它推翻了什么。那个让人安心的模型是按比例的:攻击者需要占到你数据的某个百分比,所以数据越多,他要干的活越多。而实测出来的模型是绝对量的:攻击者需要的是固定的一摞文档,所以数据越多,他要干的活一点没变。一个用 6 亿参数模型二十倍令牌量训练出来的 130 亿参数模型,被同样的 250 篇文档植入了后门。
  • 它没有证明什么。被测试的行为是刻意设得很窄、赌注很低的——一个触发短语让模型输出乱码,诸如此类——而且模型规模远在前沿之下。「任意的、有实际用处的、难以察觉的后门同样便宜」并未被确立。请把这个结果当作举证责任被翻了过来,而不是当作每一种攻击都被标价成 250 篇文档。
  • 为什么它仍然该改变你的做法。两百五十篇文档,在一个有动机的人的预算之内——他有一个博客、一个软件包注册表账号,或者对一个会被爬取的 wiki 有编辑权限就够了。此前把这份风险压住的两句话是「没人会费这个劲」和「它会淹没在噪声里」,而其中一句现在已被测量证伪。
STEP 3

你自己拥有的那些面,才是便宜的那些面。

你大概永远不会去投毒一场前沿预训练,也不太会经由它被投毒——那是别人的供应链,你买到手的是成品。真正在你控制之下的那些面,比预训练语料小得多,因此也便宜得多:真正要紧的比值是攻击者文档数比上可被检索到的文档数,而你的索引里也许只有一万篇。

  • 检索语料。任何会被爬进你的 RAG 索引的东西,都是一条写入路径:客户提交的工单、外包同事编辑的 wiki 页、外部机构发来的 PDF。这里的投毒甚至不难瞄准——攻击者是照着检索器来写的,反复使用他想拦截的那些问题的措辞,于是被投毒的那个片段,恰好在最要紧的那些查询上赢下相似度检索
  • 智能体记忆。每一个智能体既写入又读回的存储,都是一份由你没有审过的作者写就的语料:那位作者就是智能体自己,而且写的时候正受着它所读到的一切影响。参见智能体记忆,并把「智能体昨天学到了这个」当作一次未经评审就上了生产的提交。
  • 工具描述与技能。一份工具 schema、一个智能体技能,都是坐在提示词里、信任级别高过任何文档的指令,而它们来自一个不由你运营的注册表。这个面已经不是理论上会被攻击,而是已经被成规模地攻击过了。
  • 微调集与评测集。两者都很小,两者都是从生产流量里攒出来的,而流量是用户写的。被投毒的评测集是安静的那一个:它不改变行为,它改变的是你对行为的判断。
STEP 4

先守住写入路径,再限住「一句被相信的谎话」能做成什么。

没有哪个分类器能可靠地认出一篇被投毒的文档,因为好毒并不畸形——它是一篇写得像模像样、只不过内容为假或夹带了一条指令的页面。所以真正管用的控制项都很朴素、都在结构层面。

  • 搞清楚谁能写。对每一份语料,把能往里加东西的主体集合写下来。如果这个集合里包含「任何客户」或「公网上的任何人」,那你手上就是一份不可信语料,从它检索出来的一切都是不可信内容——不管装着它的那套系统感觉上有多「内部」。
  • 把「内容上可信」与「指令上可信」分开。检索回来的东西永远不该被当作指令,来源看起来多权威都不行——而指令层级对这条规则只做得到统计意义上的执行,所以它还必须由「工具肯做什么」来执行一遍。
  • 让每个片段都带着来源。出处、作者、写入时间,以及那条写入路径的信任档位,一路从建索引带进提示词。没有它,你就回答不了事故之后唯一要紧的那个问题:这位作者还往里放过什么,哪些答案用过它们?
  • 让写入可撤销。把一篇被投毒的文档从存储里删掉很容易;把它从索引、缓存、微调权重和被摘要过的记忆里弄出来就不容易了。请在你真需要删除之前,就把删除的传播设计好。
  • 假定有毒已经进来了。最后一道线不是检测,而是:一个相信了假话的模型,凭它自己仍然做不出任何不可逆的事——与应对注入的是同一套围栏。参见智能体身份与权限

这一周先做清点,别先上工具。把你的智能体会读到的每一份语料列出来——索引、记忆、技能、工具文档、评测集——并给每一份写明谁能写、谁审这次写。多数团队会发现至少有一条路径,让一个未经身份认证的陌生人写的文本中间不经任何人就抵达模型;把这一条路径堵上,比你买得到的任何检测器都值钱。然后放一只哨兵:把一个有辨识度的触发短语和一条无害的标记指令放进你自己的语料,再看它会不会哪天从某个答案里冒出来。

相关:记忆投毒防御讲写入路径的细节,智能体供应链安全讲注册表那一侧,RAG 安全讲怎么运营一份你并不完全掌控的检索语料。