同一个文件,两种权限
先看一个具体的事实。仓库里那份 AGENTS.md 或 CLAUDE.md,在 Codex 与 Claude Code 里按用户输入处理;在 Cline、Kimi CLI、OpenCode、OpenClaw、Pi-mono 与 Qwen Code 里,同一份文件被当作系统指令。
同样的内容,同样的仓库,落在不同的信任级别上。按照伊利诺伊大学研究者的说法,这不是谁有意设计的,而是各家 harness 各自实现的结果。他们把这项盘点的标题写成了一个问句:《What’s in Your Agent’s Context?》
这件事之所以重要,是因为指令层级——也就是「系统提示词优先于用户输入」这套规则——是由模型执行的,但每个内容进到哪个角色,是由 harness 分配的。边界由厂商私下划定,不需要与其他厂商一致,也不需要向用户解释。
12 个 harness,282 个入口
研究者没有停在概念层面,而是拿分析工具对着 12 个真实运行的编码智能体 harness 做了一次静态盘点。
结果是 282 处内容会在运行时被拉进模型上下文,其中 183 处以 system 角色进入——这是模型拥有的最受信任的角色。
按来源类型拆分,配置文件占了 34.4%,第三方组件(技能、MCP 服务器与子智能体)占 28.0%,记忆文件占 24.1%,剩下的是环境变量与运行时变量。
这三个占比分别指向三种不同的风险。配置文件是仓库自带的,跟着代码一起被审阅;第三方组件来自外部,安装时通常只看功能说明;记忆文件是运行过程中自己写出来的,几乎没有人在部署前审阅过。
还有一条容易被忽略的发现:12 个 harness 里,每一个都至少加载 5 个研究者称为「对用户不透明」的配置或环境来源。不透明的意思是,这些来源无法通过阅读文档枚举出来。如果连有哪些入口都列不全,那么在入口处做管控这件事就无从谈起。
上下文特权提升是怎么发生的
把这 282 个入口和「角色由位置决定」这条规则放在一起,一条攻击路径就浮出来了。
攻击者的内容先落在一个低权限来源上——比如一条 issue、一段工具返回、一个第三方技能里的说明。智能体在处理任务时把它写进了某个高权限来源,比如项目记忆文件或配置文件。下一次会话启动时,harness 按「内容住在哪里」而不是「内容从哪里来」来决定角色,于是它以系统指令的身份被加载。
这条链条上,没有内存破坏,没有构造的二进制,也没有哪个单独的步骤是违规的。harness 每一步都在按自己的设计工作,所以入口处的过滤器永远看不到异常——它检查的是内容本身,而内容本身确实没有异常。
研究者在一份演示里给出了一个具体的例子。操作员允许读取与编辑文件,同时禁用了命令执行与外部工具调用。智能体在一个 GitHub issue 里识别出了敌意内容,并按用户要求把它打印出来。问题出在打印之后:周边软件把那段引用里的命令形标签,当成了真实的文件写操作。这些写入动作植入了持久的审查指令,并弱化了智能体自身的权限设置。
这个案例的教训不是「模型不够警惕」。恰恰相反,模型正确识别了可疑内容。问题在于「描述一个操作」与「请求一个操作」这两件事,在模型产出响应之后就没有被区分开。改进模型对攻击的警告意愿,并不能让应用安全地处理这条警告。
持久化改变了调查方式
关掉一个可疑会话,并不等于其中的指令失效。
如果内容已经被写进某个会被后续会话加载的文件,那么结束对话只是结束了那次交互,控制材料还留原处。下一个任务会在完全没有遇到过原始敌意文档的情况下,继承这次改动。这意味着三件事:影响跨会话;触发它的那次交互可能早已被遗忘;而读到这条内容的智能体没有任何理由怀疑它——它看起来就是项目自身的约定。
对审计的直接要求是:一条长期生效的指令,应该能回答「它从哪里来」和「谁批准了它」。缺少这两项记录,事后调查只能从内容反推,而内容本身通常不带来源信息。
可以落地的四层控制
研究者与后续讨论给出的建议里,有几条是比较具体的。
其一,把「引用」与「执行」分开。应用应当要求一个单独标识的动作请求,才进入权限判断流程。展示给人看的文本与发出的可执行请求,即使可见内容看起来一样,也应该走不同的处理路径。这一条可以用很低成本测出来:给模型一段包含操作的内容作为引用、代码示例或被否决的建议,然后观察有没有东西真的被执行。
其二,给文件编辑权限一个更窄的定义。源文件是工作产物,而决定命令是否需要批准的那些设置,管的是工作怎么被执行。如果一个智能体可以同时改这两类文件,那一次普通编辑就能变成对它自身权限的修改。研究者强调,这是一条建议性控制,而不是说研究涉及的产品都缺这一层。
其三,权限按任务粒度收窄。同一时期的另一篇预印本给出了一套三来源的权限架构——角色权限上限、任务权限分类器与基于策略的禁止项,并做了端到端评测:用微调过的 RoBERTa-large 编码器做分类,质量与少样本训练的 Claude Haiku 4.5 相当(宏平均 F1 分别为 0.881 与 0.886,精确率 0.897 与 0.842,严重度加权残留风险 0.63 与 1.12)。论文提出的攻击面消除指标显示,仅靠角色上限能关掉 27.9% 的严重度加权攻击面,再加上任务分类器能关掉 84.4%。
这套结果里最实用的一条推论是:负责监督的组件不需要与被监督的智能体同规模。一个较小的编码器就足以承担任务粒度的权限判定,这让「给每个智能体配一个治理层」在成本上变得可行。
其四是要求厂商出版本化的上下文清单。研究者主张厂商应公布每个加载来源、它进入的角色、以及它的持久化范围。讨论里有人补了一层:清单描述的是厂商「认为自己在做什么」,而同一家厂商完全可能对自己的实现判断有误——有一个工具把技能元数据放在用户角色,却把记忆文件放在系统角色。所以清单之外还需要一个复核权,而不是一次性披露。
这条补充有一个可以量化的理由。有人统计过 35 次公开 MCP 注册表的抓取结果,覆盖 2,043 台服务器上的 44,172 个工具:83.8% 声明了规范的效果注解,而其中只有 59.3% 的注解仍与实际合约一致。清单纯粹描述某个时刻的状态,而状态会在它脚下移动。
需要说清楚的局限
其一,这是研究者自报的危害演示。客户是否真的被利用过、被测版本之外的当前版本是否仍然暴露,都没有被证实。研究覆盖的是 12 个指定的产品版本,而不是这些产品的现状。
其二,Promptfoo 的目录转述了这项研究,并明确说明没有做独立复现。评估结果的可复现性目前是未知的。
其三,282 与 183 这两个数字是静态盘点的结果,会随 harness 版本变化。它们适合当作一次快照,而不是长期结论。
其四,任务粒度权限那篇论文是在自有数据集上做的评测,600 条标注提示词由作者发布,跨机构的可比性有待验证。
把这几条放在前面,不是说这项工作没有价值,而是因为它给出的结论很容易被误用成「某个产品不安全」。更准确的读法是:在当前这批 harness 里,「谁能改运行规则」这件事缺乏统一且可枚举的约定,而这个缺口是可测量的。
目前官方及行业暂未披露更多细节,后续将持续跟进迭代动态。