NVIDIA 发布 AI Agent 安全平台:OpenShell、Sentry 如何限制 Agent 的 JSON Tool Calls?
模型仍然只填 JSON。2026 年 9 月 28 日,NVIDIA 把边界放到模型外面:OpenShell 在沙箱代理里看 tools/call 的工具名,Sentry 在 BlueField-4 上做带外隔离。允许 lookup_order 不等于允许任意 order_id。
阅读前速览
| 层 | 官方事实 | 谁挡住调用 |
|---|---|---|
| OpenShell | Apache 2.0。沙箱加内核隔离。代理检查沙箱发往 MCP 服务的请求体 | 按工具名 allow / deny。不匹配参数 |
| Sentry | BlueField-4 上的带外看门狗。越出软件边界就在毫秒级隔离。参考设计,可选 | 硬件层停执行。不填 JSON |
| 策略证明 | 网关里的 prover。新的带凭据可达、新 HTTP 方法、云元数据会挡住自动批准 | 改策略之前。不是执行时的 Schema |
| 宿主 Schema | 文档写明:允许的工具接受任意参数 | 执行前再验 arguments |
事实来自 2026-09-28 的 NVIDIA 新闻稿、技术博客,以及 OpenShell 策略文档。订单 A-1042 是虚构的。下面的 JSON 是文档 YAML 的同一组字段,不是 Sentry 的未公开线级格式。
OpenShell 挡工具名,Sentry 挡越界执行
Open Agent Safety Platform 是两块,不是又一种聊天权限。第一块是 OpenShell,Apache 2.0,现在广泛可用。它给跑在 CPU 上的 Agent 一个沙箱:内核管文件、系统调用和网络,代理再看离开沙箱的 HTTP。MCP 端点用 protocol: mcp,检查沙箱发往服务端的请求体,能按方法和 tools/call 的工具名放行或拒绝。第二块是 Sentry,参考设计。它跑在 BlueField-4 DPU 上,带外、不在 Agent 够得着的地方。Agent 越出软件边界,Sentry 在毫秒级隔离并停掉。在 Vera Rubin POD 里,这块 DPU 位于节点通往模型的唯一路径上。第三,参数不在这两层里。OpenShell 写明:工具参数匹配尚未支持,允许的工具接受服务端肯收的任意参数。
- OpenShell:
lookup_order可以放行,refund_order写进deny_rules。 - Sentry:可选的硬件层。它关联交互、策略决定和工具访问,并做身份核验。它不代替工具名单。
- 宿主:
A-1042是否合法,仍用 Schema 验arguments。
会话里的 allow / ask / deny 是另一道门,见 Coding Agent 的权限模型。MCP 的 tools/call 长什么样,见 Coding Agent 如何调用 MCP。实验室越出评测环境的事件,站内已经写过,见 Agent 安全危机与 JSON 验证。本篇不重写那些事件,只拆 OpenShell 和 Sentry 怎么挡住一次工具调用。
代理看见的是 tools/call,不是模型的散文
OpenShell 解析的是沙箱进程发往 MCP 端点的 JSON-RPC 请求。虚构订单,主机名用 orders.example.com:
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "lookup_order",
"arguments": { "order_id": "A-1042" }
}
}
它核对的是 method 和 params.name。默认还要求工具名匹配 ^[A-Za-z0-9_.-]{1,128}$,这就是 mcp.strict_tool_names,默认 true。通配的 tool 匹配器要求这个开关保持打开。arguments 里的 order_id 不参与这条策略。响应体和 SSE 上服务端发给客户端的 MCP 消息会被转发,目前不做策略解析。一批请求里有一条被拒绝,整批拒绝。
策略按工具名写,参数另开一道门
文档给的是 YAML,用 openshell policy set 整份写入。增量的 policy update --add-endpoint 还不接受 mcp。下面是同一组字段的 JSON,方便 Diff。查单放行,退款拒绝。默认 mcp.allow_all_known_mcp_methods 是 false,所以方法要一条条写。省略 mcp.versions 时,只允许 2025-11-25 这个修订:
{
"version": 1,
"network_policies": {
"orders": {
"name": "orders",
"endpoints": [{
"host": "orders.example.com",
"port": 443,
"path": "/mcp",
"protocol": "mcp",
"enforcement": "enforce",
"mcp": {
"strict_tool_names": true,
"max_body_bytes": 65536
},
"rules": [
{ "allow": { "method": "initialize" } },
{ "allow": { "method": "notifications/initialized" } },
{ "allow": { "method": "tools/list" } },
{ "allow": { "method": "tools/call", "tool": "lookup_order" } }
],
"deny_rules": [
{ "method": "tools/call", "tool": "refund_order" }
]
}],
"binaries": [{ "path": "/usr/bin/python3" }]
}
}
}
filesystem_policy 和 landlock 在沙箱创建时锁死。network_policies 可以热加载。二进制路径要写上,策略是「哪个程序可以打到哪个端点」。出站默认不放行私网,也不授权回环、链路本地和云元数据地址。允许 lookup_order 之后,参数门在宿主:
{
"type": "object",
"properties": {
"order_id": { "type": "string", "pattern": "^[A-Z]-\\d{4}$" }
},
"required": ["order_id"],
"additionalProperties": false
}
这道 Schema 不是 OpenShell 的字段。代理放行工具名之后,宿主仍要拒绝缺字段、多字段和不合 A-1042 形状的参数。Schema 为什么是门,见 AI 为什么需要 JSON Schema。
四道门不要合成一道
名字都叫安全。挡住的对象不一样:
| 门 | 它看什么 |
|---|---|
| OpenShell 代理 | 沙箱到 orders.example.com:443/mcp 的请求。方法、工具名、调用它的二进制。不看 arguments。 |
| 宿主 Schema | lookup_order 的参数。类型、必填、pattern。过了门才执行。 |
| Coding Agent 的 allow / ask / deny | 会话里的 Shell、Git、文件工具。那是 harness 的名单。OpenShell 是沙箱外的另一层。 |
| Sentry | BlueField-4 上的带外执行。越界就隔离。公开材料没有给出一份 Sentry 的 JSON 字段表,不要用本篇的策略对象冒充它。 |
策略改动在生效前还可以过 prover。它标出新的带凭据可达、新的 HTTP 方法、对云元数据的访问。有发现就不自动批准。命令行工具是 openshell-prover,可以放进 CI。Agent 只能经 Policy Advisor 提交窄提案,批准发生在沙箱外面。环和状态怎么落,见 Agent Harness 与 JSON State。
六步再放宽一条规则
不要从「先开 Sentry」开始。先写清哪一次调用被哪一层挡住:
- 把模型 JSON 和运行时策略分开。模型填
params.name。OpenShell 决定这个名字能不能离开沙箱。 - 创建沙箱时写好文件系统和 Landlock。这两段之后不能当网络规则热加载。
- MCP 端点写全。
host、port、path: /mcp、protocol: mcp、enforcement: enforce。不要和别的协议共用同一主机和端口。 - 工具名一条条写。
initialize、notifications/initialized、tools/list,再加tools/call加lookup_order。refund_order放进deny_rules。strict_tool_names保持 true。 - 参数交给宿主 Schema。代理不读
order_id。退款如果被塞进一个已允许工具的参数里,这层不会看见。 - 放宽之前做 Diff,并用 prover。Sentry 是 BlueField-4 上的可选层。没有这块 DPU,不要把隔离写成已经发生。
一批 JSON-RPC 里只要有一条被拒绝,整批被拒绝。查单不要和退款打在同一个批里试探。服务端响应不在这条策略里。
放宽规则前摊开三份对象
一次被拒,先分清是工具名、二进制路径、主机端口,还是参数形状。
- 把
tools/call和策略 格式化,再用 Schema 校验 看arguments是否过门。 - 用 JSONPath 提取 抽出
$.params.name、$.method、$.arguments.order_id。 - 用 JSON Diff 对比放宽前后的
network_policies。先看多出来的 tool,再改提示。 - 沙箱日志看被拒的 host、path 和 binary。
openshell logs --tail --source sandbox。 - 日志里的令牌先 脱敏。订单和密钥不要贴进公共格式化站。JSONSort 在浏览器本地跑。
三份对象对得上,才算知道是哪一层挡住了 refund_order。Sentry 的隔离记录不在这三份 JSON 里。
常见误区
- 把 OpenShell 当成会话里的 allow / ask / deny。那是 harness 的名单。OpenShell 是沙箱代理和内核。两份策略都要在。
- 以为允许了工具名就验过了 order_id。文档写明参数匹配尚未支持。宿主 Schema 不能省。
- 只检查模型回复。代理看的是发往 MCP 端点的请求体。响应和 SSE 目前不解析。
- 让沙箱自己批准策略。Policy Advisor 只提交提案。批准在沙箱外。prover 有发现就不自动批准。
- 把 Sentry 写成一份 JSON Schema。公开材料写的是 BlueField-4 上的带外隔离和关联记录。没有线级字段表,就不要编。
- 用本篇重写越狱事件。那些事件站内已经写过。这里只写边界怎么挡一次
tools/call。
FAQ
Sentry 能代替 OpenShell 吗?
不能。OpenShell 是软件运行时,管沙箱、内核和出站策略。Sentry 是 BlueField-4 上的可选带外层,越界时在毫秒级隔离。没有这块 DPU,就只有 OpenShell 那一层。两层都在模型外面。
代理会读 tools/call 的参数吗?
不会。它匹配方法和工具名。允许的工具接受任意参数。一批请求里有一条被拒绝,整批拒绝。参数形状由宿主的 Schema 再验一遍。
这和 Cursor、Claude Code 的权限文件是一回事吗?
不是。那些文件决定会话里的 Shell、Git 和文件工具能不能跑。OpenShell 决定沙箱里的哪个二进制能不能对哪个主机端口发出 MCP 请求。一个在 harness 里,一个在沙箱边界上。
prover 挡住的是什么?
它在策略生效前做形式化检查。新的带凭据可达、新的 HTTP 方法、对云元数据的访问会被标出,有发现就不自动批准。它不代替执行时的工具名规则,也不代替 Schema。
服务端的 MCP 响应也会被策略过滤吗?
按当前文档,不会。JSON-RPC 响应,以及响应体或 SSE 上服务端发给客户端的 MCP 消息,会被转发,不做策略解析。你要核的是离开沙箱的那份请求。
结论
NVIDIA 这套平台把工具调用的边界放到模型外面。OpenShell 按 MCP 的工具名放行或拒绝。Sentry 在 BlueField-4 上把越界执行隔离开。参数仍由宿主用 Schema 验。
先写清 lookup_order 在 rules 里,refund_order 在 deny_rules 里,A-1042 在宿主 Schema 里。三处对得上,这次调用才算被限制住。
延伸阅读
- Coding Agent 的权限模型 allow / ask / deny,和沙箱不是同一层
- Coding Agent 如何调用 MCP tools/call 的 JSON-RPC 形状
- Agent 安全危机与 JSON 验证 事件已经写过,本篇不重写
- Agent Harness 与 JSON State 环、门、状态
- 为什么 AI 需要 JSON Schema Schema 是门
- JSONSort 本地工具箱 格式化、校验、Diff、Schema
- 全部文章 更多 JSON 与 AI 开发笔记
更新记录: 首次发布