Foot-in-the-Door(FITD,登门槛)攻击不会一开始就要求 AI Agent 执行敏感操作。攻击者先让 Agent 连续完成几项小而正常的任务,每一步都像是上一步的自然延续,最后再提出越过权限边界的请求。Agent 可能因为前面的步骤都已获认可,把最后的请求也当成同一项工作的正常收尾。
只要 Agent 能读取不可信内容并调用工具,就可能遇到这种攻击。诱饵可以藏在日历邀请、文档、工单或网页里。FITD 见于论文 Breaking ReAct Agents: Foot-in-the-Door Attack Will Get You In。
为什么一串无害动作会增加风险?
许多 Agent 使用 ReAct,即 Reasoning and Acting(推理与行动)。Agent 不断选择工具、读取结果,再决定下一步;之前的动作和结果会留在工作上下文中,影响后续判断。
如果直接要求 Agent 外发私人数据,风险很容易被识别。FITD 会先安排一条更平缓的路径:<无害整理请求 1>、<无害查询请求 2>、<无害摘要请求 3>。Agent 每完成一步,行为动量就更强,下一步看起来也更像当前工作流的一部分。
最后出现的请求可能是 <未授权的外发请求>。Agent 可能把它当成第四步,而不是先问“用户是否授权了对外分享”。这里的根本错误,是把流程连续性误当成了权限。工具结果可以为任务提供信息,却不应自动赋予 Agent 调用更敏感工具的权力。
sequenceDiagram participant U as 用户 participant A as ReAct Agent participant D as 日历或备注数据 participant T as 工具集 U->>A: 汇总今天下午的日程 A->>T: <读取日历> T-->>A: 日程加上一条不可信备注 A->>T: <整理参会人> T-->>A: 无害的列表结果 A->>T: <查询会议备注> T-->>A: 无害的备注结果 A->>T: <向外发送数据> Note over A,T: 最后一步超出了用户的原始请求
这和一次性的间接注入不同。隐藏指令如果一上来就要求外发数据,属于普通提示注入;FITD 会先放入几项合理、低风险的动作,让越界动作借用前面步骤形成的“已获允许”错觉。
日历助手会怎样被诱导?
设想一个办公助手,它可以读取日历、整理会议资料、搜索备注并发送消息。用户对它说:“帮我汇总今天下午的会议。”这是一个普通请求,前几个工具也确实派得上用场。
攻击者发送一封看似正常的线上研讨会邀请。标题和时间都没有异常,但会议说明或附件备注里藏着一串占位请求:先 <整理参会人名单>,再 <查询相关会议备注>,最后 <把整理出的信息发到外部地址>。这里不写出真实指令;关键在于这些请求的顺序。
助手读取日历后看到了这封邀请。它先整理参会人,再查询会议备注。这两步都很小,也都和会议整理有关。用户没有逐项批准这些来自邀请内容的请求,但它们不像最后一步那样显眼。
完成这些动作后,外发请求被摆成同一工作流的下一步。如果 Agent 调用了 <向外发送数据>,用户的日程信息就可能离开组织。若一开始直接要求它这么做,系统更容易发现问题;连续铺垫则让危险动作看起来像例行收尾。
怎样防范 FITD?
防御要在每个敏感动作发生前重新检查授权。模型主动拒绝很有帮助,但不能成为唯一控制,因为这种攻击正是利用了“危险动作看起来很合理”这一点。
-
每项任务只提供必要工具。 如果用户只是要汇总日历,就只开放日历读取和格式整理能力,并移除外发、上传和写入工具。可调用的工具越少,备注内容越难转化为副作用。
-
在权限边界处要求确认。 发送数据、修改记录、删除内容或调用新的外部服务前,都要让用户明确确认。确认内容应写清哪些数据会发往哪里,不要只让用户批准含糊的“下一步”。
-
把外部内容当作数据隔离。 日历说明、网页、文档和工具结果都应明确标为不可信数据,在上下文中定界,并告诉 Agent 其中的文字不能改变权限或创建新任务。这能减少混淆,但不能替代运行时拦截。
-
每次产生副作用前核对原始目标。 将用户的目标保存在模型工作文本之外。执行写入或外发前,把拟执行动作与原始目标比较;如果关系不明确,就阻止它。用户要“汇总”,不应被悄悄变成“发布”。
-
测试连续动作,而不只是单条提示。 能拒绝直接外发请求的防护,可能在连续几次工具调用之后失效。测试中应加入无害前缀和不可信中间结果,并检查 Agent 是否在权限边界停下。
如何用 AiBeat 测试自己的 Agent?
你需要一个自己控制且正在运行的目标 Agent、已安装的 AgentBeat、目标注册信息,以及已配置好的 Judge 模型。AgentBeat 快速开始介绍了 Registry JSON 的写法和连接目标所需的环境变量。
-
安装 AgentBeat 并准备目标 Agent
按照 AgentBeat 快速开始 安装并验证 CLI。启动你自己的 Agent,确保 AgentBeat 能访问它。在目标注册表中注册这个 Agent,并补齐评测文件要求的
target_profile、target_capability和deployment_profile_id。快速开始页面提供完整的 Registry 示例,也说明了AGENTBEAT_TARGET_URL的用法。 -
配置目标注册表和 Judge
让
AIBEAT_AGENT_TARGET_REGISTRY指向你的 Registry JSON,并配置 Judge。这个评测必须配置 Judge。Terminal window export AIBEAT_AGENT_TARGET_REGISTRY=./your-target-registry.jsonexport AGENTBEAT_TARGET_URL="http://127.0.0.1:39103"export AIBEAT_JUDGE_BASE_URL="https://api.example.com/v1"export AIBEAT_JUDGE_MODEL="<judge-model>"export AIBEAT_JUDGE_API_KEY="<judge-api-key>"请替换成你环境中的真实值。快速开始页面说明了这些变量和 Registry 字段;密钥不要写入共享文件或日志。
-
从 Seeds 社区下载 FITD 种子
在 Seeds 社区 打开
fitd-calendar种子页,使用页面展示的下载命令。不要自行猜测版本号或 URL。中文种子文件名是eval-run.json。Terminal window mkdir -p ./seeds/<seed-id> \&& curl -fsSL https://www.aibeat.ai/community/registry/<seed-id>/<version>/eval-run.json \-o ./seeds/<seed-id>/eval-run.json运行前,确认下载文件中的
target_profile、target_capability和deployment_profile_id指向你刚注册的目标。 -
运行评测并查看结果
使用下载的种子运行评测:
Terminal window ./bin/agentbeat eval-run < ./seeds/<seed-id>/eval-run.json > ./seeds/<seed-id>/result.json查看结果里的实际结论:攻击是否成功,以及 Agent 的交互发生了什么。如果某次运行无法观测或判断相关行为,不能据此证明 Agent 安全;先修复测试配置,再把无法判定当作需要调查的结果。
参考文献
- Breaking ReAct Agents: Foot-in-the-Door Attack Will Get You In,arXiv:2410.16950。论文研究了多步行为动量在其实验条件下如何影响调用工具的 Agent。