AI 開発

NVIDIA の AI Agent 安全基盤:OpenShell と Sentry は JSON Tool Call をどう制限するか

約 16 分

モデルは 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 はこのポリシーに入らない。JSON-RPC 応答、および応答本体や 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 の形に合わない order_id を拒む。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 を先に開けない。どの呼び出しをどの層が止めたかを先に書く:

  1. モデルの JSON と実行時ポリシーを分ける。モデルは params.name を埋める。OpenShell がその名前がサンドボックスを出られるかを決める。
  2. サンドボックス作成時にファイルシステムと Landlock を書く。この二つはネットワーク規則のようにはホットリロードしない。
  3. MCP 端点を埋める。host、port、path: /mcp、protocol: mcp、enforcement: enforce。別プロトコルとそのホストとポートを共有しない。
  4. ツール名を一行ずつ書く。initialize、notifications/initialized、tools/list、それから tools/call に lookup_order。refund_order は deny_rules。strict_tool_names は true のまま。
  5. 引数は宿主の Schema に渡す。プロキシは order_id を読まない。許可済みツールの引数に返金を押し込んでも、この層は見ない。
  6. 広げる前に Diff し、prover を走らせる。Sentry は BlueField-4 の任意層である。その DPU がなければ、隔離を既に起きたこととして書かない。

JSON-RPC のバッチで一条が拒否されると、バッチ全体が拒否される。照会と返金を同じバッチで試さない。サーバ応答はこのポリシーの外にある。

規則を広げる前に、三つの対象を広げる

拒否はツール名か、バイナリのパスか、ホストとポートか、引数の形か。プロンプトを直す前に分ける。

  • tools/call とポリシーを 整形 し、Schema 検証 で arguments が門を通るか見る。
  • JSONPath 抽出 で $.params.name、$.method、$.arguments.order_id を抜く。
  • 広げる前後の network_policies を JSON Diff する。プロンプトの前に、増えた 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 にある、と先に書く。三箇所が揃って、この呼び出しは制限されたことになる。

あわせて読む

更新記録: 初出