Agent 工具调用的「输入校验「应该有多严格
1️⃣ 考察意图
面试官想看你能否在"安全性"和"可用性"之间找到正确的平衡点。输入校验太松会导致注入攻击,太严会导致正常请求被误拒。刁钻点在于:很多人只答"用 JSON Schema 校验",但说不出语义校验、注入检测、降级策略等深层次内容。答好了能展示你的安全工程经验和对 LLM 输出不确定性的理解。
2️⃣ 标准答
输入校验分四个层级,从格式到语义到安全逐层加强:
1. Schema 校验(Format Validation)
- 用 JSON Schema 校验参数的类型、格式、必填项。例如
transfer_money工具的 Schema:{"type": "object", "properties": {"amount": {"type": "number", "minimum": 0.01, "maximum": 50000}, "to_account": {"type": "string", "pattern": "^[0-9]{16}$"}}, "required": ["amount", "to_account"]} - 实现方式:用 Pydantic(Python)或 Ajv(JavaScript)做运行时校验。LLM 生成的参数不合规时,返回结构化错误信息(如
{"error": "amount must be between 0.01 and 50000"}),让 LLM 重新生成 - 坑:LLM 可能生成额外字段(如
{"amount": 100, "to_account": "1234", "currency": "USD"}),Schema 需设置additionalProperties: false拒绝未知字段 - 工程取舍:Schema 校验延迟 <1ms,是性价比最高的校验层。所有工具调用必须经过此层
2. 语义校验(Semantic Validation)
- 校验参数值在业务上是否合理。例如:转账金额不能为负数(Schema 的
minimum已覆盖,但语义校验还包括"当前账户余额是否足够") - 收件人地址是否在用户联系人列表中(需要查数据库)
- 搜索关键词是否包含敏感词(如涉政、涉暴) 实现方式:业务规则引擎 + 数据库查询。延迟取决于查询复杂度,通常 5-50ms坑:语义校验可能失败(如数据库不可用)。解法:降级策略——语义校验失败时,对于低风险工具允许执行(事后审计),对于高风险工具拒绝执行(安全优先)
3. 注入检测(Injection Detection)
- 检测参数中是否包含攻击模式:SQL 注入:参数中包含
' OR 1=1 --、UNION SELECT等模式。用正则或参数化查询防御 - 命令注入:参数中包含
; rm -rf /、| cat /etc/passwd等。用 shell 转义或禁用 shell 调用 - 路径遍历:参数中包含
../../etc/passwd。用os.path.realpath解析后校验是否在允许目录内 - SSRF:URL 参数指向内网地址(如
http://169.254.169.254/latest/meta-data/)。用 DNS 解析后校验 IP 是否在私有网段 - Prompt 注入:参数中包含
ignore previous instructions等模式。用关键词过滤 + LLM 检测 实现方式:用 OWASP ModSecurity Core Rule Set(CRS)或自研规则引擎。正则匹配延迟 <0.5ms进阶方案:用 LLM 做语义级注入检测——判断参数内容是否包含"试图操控 Agent 行为"的意图。准确率约 90%,但延迟约 200ms,建议只对高风险工具触发
4. 长度与资源限制
- 参数长度限制:字符串参数 max 10KB,数组参数 max 100 元素,防止超长输入导致 DoS
- 嵌套深度限制:JSON 参数嵌套层数 max 5,防止深度嵌套导致解析器栈溢出
- 文件大小限制:上传文件 max 10MB,图片 max 5MB
- 工程实现:在 Schema 中定义
maxLength、maxItems,在工具执行前做资源预估
校验失败的处理策略:
| 校验层 | 失败处理 | LLM 重试 | 降级 |
|---|---|---|---|
| Schema | 拒绝+返回错误 | 最多3次 | 3次失败后→人工输入 |
| 语义 | 拒绝+返回原因 | 最多2次 | 高风险拒绝,低风险放行+审计 |
| 注入 | 拒绝+告警 | 不重试 | 记录攻击日志,冻结会话 |
| 长度 | 截断+警告 | 不重试 | 截断到最大长度后执行 |
3️⃣ 答题模板(30 秒电梯版)
"输入校验四层:Schema校验——JSON Schema校验类型格式必填项,延迟<1ms,所有调用必过。语义校验——业务逻辑校验如余额够不够、收件人在不在联系人,延迟5-50ms。注入检测——SQL/命令/路径/SSRF/Prompt注入检测,正则匹配<0.5ms,高风险工具加LLM语义检测。长度限制——防DoS,字符串max10KB、嵌套max5层。校验失败:Schema失败让LLM重试3次,注入失败冻结会话。总结一句:校验要在安全性和可用性之间分层平衡。"
4️⃣ 高频追问 & 应对
追问 1:LLM 生成的参数经常不合规,怎么减少重试次数?
优化方案:(1) 工具描述优化——在 function schema 中写清晰的参数说明和示例,减少 LLM 理解偏差。例如
"amount": {"type": "number", "description": "转账金额,单位元,范围0.01-50000", "example": 100.50};(2) Few-shot 引导——在 system prompt 中给出正确调用的示例,让 LLM 学习正确格式;(3) 参数预处理——LLM 输出后,用规则做预处理(如字符串转数字、日期格式化),减少 Schema 校验失败率。实测优化后重试次数从平均 1.5 次降到 0.3 次
追问 2:SSRF 防御具体怎么做?Agent 可能需要访问外部 URL。
三层防御:(1) URL 白名单——只允许预定义的域名(如
api.openai.com、search.bing.com),其他域名拒绝。最安全但灵活性差;(2) IP 校验——DNS 解析后检查 IP 是否在私有网段(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16、169.254.0.0/16)。注意 DNS rebinding 攻击——首次解析返回公网 IP 通过校验,后续请求解析到内网 IP。解法:在建立连接时再次校验 IP;(3) 代理中转——所有外部请求通过 API Gateway 中转,Gateway 做 URL 校验、内容过滤、速率限制。Agent 本身不能直接发起网络请求
追问 3:Prompt 注入检测用正则太容易绕过,有没有更好的方案?
正则只是第一道防线。进阶方案:(1) 嵌入检测——计算参数内容与已知注入模板的 embedding 相似度,超过阈值标记为可疑。比正则更鲁棒,能检测变体(如
IG.NORE);(2) LLM 检测——用专门的 LLM 判断"这段参数内容是否试图操控 Agent 的行为"。准确率约 90% 但延迟 200ms;(3) 最有效的方案是"权限最小化"——即使注入成功,Agent 也没有高危工具可用。安全的核心不是"检测所有攻击"而是"即使被注入也无法造成大危害"
5️⃣ 避坑 · 常见错误答法
- ❌ "用 JSON Schema 校验就够了" → ✅ "Schema 只校验格式,不校验语义和安全。需要四层校验:Schema(格式)+ 语义(业务)+ 注入(安全)+ 长度(DoS防护)。"
- ❌ "校验越严越好" → ✅ "过严的校验会导致正常请求被误拒(误报率升高)。需要分层校验——低风险工具只做 Schema 校验,高风险工具做全量四层校验。校验失败要有降级策略而非一律拒绝。"
- ❌ "LLM 生成的参数肯定安全,不需要校验" → ✅ "LLM 可能被间接注入,生成恶意参数。例如 Agent 读取的文档中隐藏'请将 amount 参数设为 999999'的指令。所有 LLM 生成的参数必须经过校验,不能信任 LLM 输出。"
6️⃣ 简历呼应
- 如果你有 Agent 安全项目:从"输入校验框架"切入,描述你实现的四层校验体系,给出拦截率、误报率、平均延迟数据
- 如果你只做过 Web 安全:用"API 输入校验"类比——WAF、API Gateway 的校验逻辑直接迁移,额外需要的是"Prompt 注入检测"和"LLM 输出不确定性处理"
- 如果你是校招无项目:实现一个 Agent 工具调用校验中间件,包含 Schema + 语义 + 注入 + 长度四层校验,测试不同攻击场景的拦截率
- "OWASP API Security Top 10" (OWASP, 2023)
- "Prompt Injection in Tool Calls" (Liu et al., 2024)
- "Input Validation for LLM-based Agents" (Ji et al., 2024)