AI

租户 ID 写成工具参数,等于交给随机代理人(中英切换)

租户 ID 写成工具参数,等于把钥匙交给随机代理人。

多租户工具习惯让调用方传 tenant_id,再对照 entitlement 校验——看起来正确,对人类 API 也够用。换成 LLM agent 就不行了:选哪个租户的,是模型;模型上下文里可能已经塞进了攻击者的指令。校验通过,只说明「它有权碰这个集合」;真正读哪家,仍由随机代理人决定。

租户 ID 是随机代理人

校验正确,照样全放行

The Stochastic Deputy(arXiv:2609.14780) 把这叫作参数介导授权的随机代理人变体。硬数字来自 373 次消融(八模型配置 × 两种传输):

  • Arm A(工具带 hotel_id,服务端对 entitlement 正确校验):每一次越权尝试都被服务——26/26;合理借口向量合计 26/41
  • Arm B(工具签名去掉租户参数,作用域从会话凭证绑定):工具接口无法表达跨租户读;
  • 仍有 12/56 次靠伪造可写作用域(shell / 文件系统)逃出接口——说明「接口不变式」还需要密码学保护的上下文,而不是只删参数;
  • 生产级多 GB 共享 schema 上,集合作用域 + 函数包裹成员谓词测得 57× 延迟比;JSON_TABLE 侧向连接可把租户键重新拉回索引路径。

这不是 SQL 注入,也不是漏校验。系统按设计工作——设计把钥匙交给了会掷骰子的代理人。

作用域必须在 agent 之下

结构修法不是「再写一条提示别读别的酒店」。论文的 Arm C(参数 + 提示防御)与 Arm A 同属「选择仍可表达」一族;真正关掉选择器的是:从 MCP 工具 schema 里删掉租户身份,把范围绑到已验证凭证,并在 agent 以下强制执行。凭证向下流;agent 输出没有任何路径能改作用域。

今晚只改一处判定

别再把「校验过的 tenant_id 参数」当成多租户安全边界。今晚改一处:MCP 工具签名里不允许出现租户选择器;作用域只从会话凭证派生,在工具服务器 / DB 层强制。校验正确仍可能全放行——因为钥匙在随机代理人手里。

A tenant_id tool parameter hands the key to a stochastic deputy.

Multi-tenant tools usually let the caller pass tenant_id and validate it against entitlement — correct for human APIs. LLM agents break the assumption: the model picks the tenant, and its context may already hold attacker instructions. Passing validation only proves “entitled to that set”; which tenant actually gets read is still chosen by a stochastic deputy.

A tenant_id is a stochastic deputy

Correct validation still served every attempt

The Stochastic Deputy (arXiv:2609.14780) names this the stochastic-deputy variant of parameter-mediated authorization. Hard numbers from a 373-trial ablation across eight model configurations and two transports:

  • Arm A (tool takes hotel_id, server correctly validates entitlement): every out-of-scope attempt was served — 26/26; plausible-pretext trials overall 26/41;
  • Arm B (tenant argument removed; scope bound from the session credential): no tool signature could express the cross-tenant read;
  • Still 12/56 trials escaped by forging writable scope (shell / filesystem) — interface invariance needs cryptographically protected context, not parameter deletion alone;
  • On a multi-GB shared-schema production dataset, set-valued scope under function-wrapped membership predicates measured a 57× latency ratio; a JSON_TABLE lateral join recovered indexed access on the tenant key.

No SQL injection. No bypassed check. The system worked as designed — and the design handed the key to a dice-rolling deputy.

Scope must live below the agent

The structural fix is not “add a prompt never to fetch another hotel.” Arm C (parameter + prompt defense) still leaves tenant selection expressible, like Arm A. What closes the selector: remove tenant identity from the MCP tool schema, bind scope to a verified credential, and enforce it below the agent. Credentials flow downward; agent output has no path that can rewrite scope.

One judgment change tonight

Stop treating a validated tenant_id tool parameter as the multi-tenant boundary. Change one thing tonight: no tenant selector in the MCP tool signature; derive scope only from the session credential and enforce it in the tool server / DB layer. Correct validation can still serve every attempt — because the key sits with a stochastic deputy.