サンドボックスポリシー、ゲストサンドボックス、カーネル・セントリー

すべてのマシンは、すでにワイヤ境界の内側で動いています:エージェントが持つのは代用の認証情報だけで、送るものはすべて Mac 上の Bromure のプロキシと仮想スイッチを通ります(認証情報とワイヤ境界を参照)。サンドボックスポリシー は、それ以外にマシンが何をしてよいか — VM がどこに接続してよいか、そして望むなら、エージェントが VM の中で何に触れてよいか — を決めます。マシン(設定エディタでは「ワークスペース」)は、設定 › サンドボックスポリシーで 2 つの サンドボックスエンジン のどちらかを選びます:

Bromure FirewallOpenShell + Sentry
書くもの許可/拒否ルールの順序付きの表(pf 形式)、既定の拒否は任意NVIDIA OpenShell のサンドボックスポリシー(YAML、スキーマ v1)
一致しない通信の既定許可(または拒否)拒否
リクエストの検査ホストごとの HTTP メソッド(web ルール)REST、WebSocket、GraphQL、MCP、JSON-RPC をリクエストごとに、enforce または audit で
VM の中なしゲストサンドボックス(ファイルシステム、プロセス、バイナリ)、カーネル・セントリー、root なしのパッケージ
ブロックの解除時間制限付きのルール、セキュリティ タイムラインのクイックアクション、Sandbox ドロワーSandbox ドロワー、http://policy.local の ポリシーアドバイザー
向いている用途マシンの働き方を変えずにネットワークを絞る端から端まで閉じ込め、観察し、監査できるようにしたいマシン

新しいマシンは Bromure ファイアウォールで始まります。どちらのエンジンも、エージェントの手が届かない Mac 上で実施され、すべての判定はセキュリティ タイムラインの 1 行になります。

次の 5 つの保護は、どちらのエンジンでも働き、ガードレール › 保護機能にあります:

  • ポリシーがブロックしたときのエージェントへの通知;
  • エージェント・ウォッチドッグ;
  • 認証情報の厳格モード;
  • 透過的な傍受;
  • リクエストごとの安全でないバイパス。

Bromure ファイアウォール

ファイアウォールは、VM が開くすべての接続にかかるルールのリストです:ホスト、IP/CIDR、プロトコル、ポート、そして Web 通信なら HTTP メソッド。ルールは上から下へ照合され、最初に一致したものが決め、オフにしたり期間を限ってオンにしたりできます。照合は仮想スイッチで(宛先アドレスと、VM が名前解決した名前で)、さらにプロキシで(TLS のサーバー名と、web ルールではメソッドで)行われます。VM の 80 番と 443 番ポートはプロキシに迂回されるので、中の何ものもすり抜けられません。ルールの書き方とエディタはサンドボックスポリシー › Bromure ファイアウォールで説明しています。

OpenShell ポリシー

NVIDIA OpenShell は、AI エージェントをサンドボックスに入れるためのオープンな形式です:エージェントがどのエンドポイントに届いてよいか、そのリクエストをどう検査するか、どのファイルに触れてよいか、どのプログラムがそうしてよいかを、1 つの YAML ポリシーで記述します。Bromure は OpenShell ポリシーをネイティブに実行します。OpenShell 用に書いたポリシーを持ち込んでも、Bromure のスターターポリシーから始めても、同じ判定が得られます。Bromure の評価器は、12 万 5000 件を超える差分テストで OpenShell 自身の評価器と照合され、食い違いは 1 件もありませんでした。

マシンの設定で OpenShell + Sentry を選ぶと、組織の既定ポリシー、またはスターターポリシー(GitHub、読み取り専用の npm と PyPI、Ubuntu のパッケージミラー)が読み込まれ、カーネル・セントリーがオンになります。それ以降は、network_policies のルールが許可しない限り、すべてが拒否されます。

ポリシーが実施される場所

場所決めること
仮想スイッチすべての接続を、アドレスとポート(全プロトコル)で、そして Enforce binaries があれば開いたプログラムで。
TLS のサーバー名/HTTP の Host接続がどのエンドポイントに属するか。プロキシ設定を飛ばす接続も含みます。
プロキシHTTPS_PROXY 経由の接続。
各リクエストprotocol(rest、websocket、graphql、mcp、json-rpc)を持つエンドポイントは、リクエストごとに検査されます:メソッドとパス(access: read-only、read-write、full、または明示的なルールと deny_rules)、クエリパラメータ、GraphQL の操作、MCP のツール、JSON-RPC のメソッド。enforcement: enforce はブロックし、audit は記録して通します。

一部の宛先は、ポリシーが何と言おうと拒否されます:

  • ループバック、リンクローカル、クラウドのメタデータのアドレス;
  • Kubernetes のコントロールプレーンのポート(2379、2380、6443、10250、10255)。

プライベートな範囲(10/8、172.16/12、192.168/16、100.64/10)には、正確なホスト名か allowed_ips を通してしか届きません。ネットワークのルールは実行中のマシンにすぐ適用されます。ファイルシステム、プロセス、セントリーの設定は次の VM 起動時から有効です。

拒否されたリクエストは、OpenShell 独自の policy_denied 本文付きの HTTP 403 を受け取るので、OpenShell を理解するツールやエージェントは同じように反応します。

Bromure が自動で追加するルール

マシンは、エージェントのモデルプロバイダー、認証情報の宛先のホスト、Kubernetes クラスタ、AWS、ローカルモデルには引き続き届く必要があります。OpenShell のプロバイダールールと同じく、Bromure はそのための _provider_… ルールを追加します。これらは Governance カードの Rules Bromure adds automatically に並び、書き出したポリシーには含まれません。

OpenShell での認証情報

Bromure の認証情報の保護は変わりません:VM が持つのは代用品で、本物の値はワイヤ上で、その認証情報自身のホストに対してだけ差し替えられます。OpenShell マシンの認証情報ペインには、2 つの追加があります:

  • OpenShell のプロバイダープロファイル — プロファイルをインポートし(openshell profile export)、値を入力すると、それぞれがプロファイルのホストとパスに結び付いたマシンの認証情報になり、プロファイルのエンドポイントがルールとして追加されます。
  • Use OpenShell credential placeholders — エージェントには、Bromure の本物そっくりのトークンの代わりに、OpenShell のもとと同じく openshell:resolve:env:NAME が見えます。

ポリシー自身の認証情報フィールド(credential_binding、credential_signing など)は警告付きで無視されます:Bromure が各認証情報をそのホストに結び付け、AWS のリクエストには自分で署名するからです。

OpenShell との違い

Bromure は OpenShell の意味論に従いますが、意図的な違いがいくつかあります:

  • filesystem_policy がなければ、ファイルシステムのサンドボックスもなし。 このセクションのないポリシーでは、VM のファイルは閉じ込められません。OpenShell なら、エージェントを作業フォルダに閉じ込めます。
  • binaries には Enforce binaries が必要。 これがないと binaries は参考情報にすぎず、エディタも警告します:エージェントは VM の中で root を持つので、プロセスの身元は信用できません。
  • ミドルウェア。 動くのは、redact モードの組み込みミドルウェア openshell/regex だけです。外部のミドルウェアは、その fail_open / fail_closed に従って素通しかブロックになります。
  • プロバイダープロファイル。 refresh する認証情報や token_grant を使う認証情報は、静的な値として使われます。
  • Seccomp。 VM のターミナルでジョブ制御が使えるよう、フィルタが調整されています。

ゲストサンドボックス

ネットワークポリシーは、VM がどこに接続できるかを制限します。ゲストサンドボックスは、エージェントがその中で何をできるかを制限します。これはポリシーの 3 つの部分から来ます:

ポリシーのセクションBromure が適用するもの
filesystem_policy(+ landlock)エージェントは、ポリシーが挙げたパスしか読み書きできません。Linux Landlock で実施され、VM の root でも解除できません。landlock.compatibility: best_effort はパスが使えないとき縮退し、hard_requirement はフェイルクローズします。
process(run_as_user、run_as_group)エージェントはそのアカウントで、sudo も Docker もなしに動きます。ホームは引き続き /home/ubuntu に見えるので、設定はそのまま効きます。
Enforce binaries(厳格なサンドボックス)VM 内の root 所有のアテスターが、各接続をそれを行ったプログラムに結び付け、ルールの binaries がそれを名指ししていなければなりません。各プログラムのハッシュは初回使用時に固定され、変更されたバイナリは拒否されます。この報告を信頼できるものにするため、エージェントは root に至るあらゆる道を失います:sudo も Docker もなく、すべての通信が透過的な傍受を通ります。

各部分は、存在する場合にだけ適用されます。filesystem_policy も process もないポリシーは、VM の中で何も閉じ込めません。process セクションがあれば、それだけで Enforce binaries がオンになります。

構成得られるもの
ネットワークポリシーのみネットワークは閉じ込められますが、VM は閉じ込められません。
filesystem_policy あり、バイナリは強制しないファイルは root に対してさえ閉じ込められます。sudo は使えるままなので、エージェントは VM 内の Bromure の補助プロセスを止められてしまいます — Sandbox カードがそれを警告します。
Enforce binaries、または process セクションファイル、システムコール、権限が閉じ込められます。エージェントは root になれず、Bromure のプロセスに干渉することもできません。

Bromure は、自分の配管に必要なわずかなパスを、書き込む必要がない限り読み取り専用で追加し、Sandbox カードに一覧にします(Added for Bromure: …):

  • ターミナルのソケット;
  • meta 共有;
  • /proc;
  • DNS の設定;
  • /usr の外にあるエージェントのインストールフォルダ(Grok は /opt/grok、Oh My Pi のランタイムは /opt/bun)。

これらがあなた自身のリストに混ぜ込まれることはありません。

フェイルクローズ

サンドボックスが、黙って閉じ込めなしの実行に戻ることはありません:

  • 厳格なサンドボックスが完全に適用されなければ、セッションは始まらず、バイナリのルールはすべてを拒否し、Sandbox カードが赤でそう伝えます。VM を再起動すると再試行されます。
  • Bromure があなたの代わりにマシンで実行するコマンド — ターミナル、vm exec、ファイル操作、git、プランナー — は、サンドボックスが立ち上がるのを待ちます(単純なコマンドなら 90 秒)。立ち上がらなければ、コマンドは sandbox unavailable: … で失敗します。
  • Bromure 自身がマシンの中で行う git の呼び出しは、常に閉じ込められた状態で動きます。リポジトリは git に好きなプログラムを指させられるからです。

root なしのパッケージ

閉じ込められたエージェントには root がないので、システム全体へのインストールはできません。Sandbox カードにある 2 つのスイッチ(どちらも既定でオン)が、インストールを機能させます:

  • Packages in the home folder — pip install は ~/.local に入ります(npm はもともと ~/.npm-global にグローバルインストールします)。VM 内の Bromure 自身のプロセスはホームフォルダのパッケージを無視するので、エージェントがそこにコードを仕込むことはできません。

  • System packages on request — エージェントが apt-get install を(sudo の有無にかかわらず)実行すると、リクエストは失敗せずにあなたを待ちます。エージェントには次のように見えます:

    bromure: this sandbox has no root. Asked the user to approve installing: libpq-dev
    bromure: waiting for their decision (Sandbox drawer › Proposals)…
    

    Sandbox ドロワーの Proposals タブを開き、Install か Reject を選びます。承認されたパッケージは、VM の root スーパーバイザーが Ubuntu のミラーから、正確な名前でだけインストールします:オプション、ファイルパス、.deb ファイル、apt がパターンや削除と解釈する名前は受け付けません。却下されたリクエストは、再試行しないようエージェントに伝えます。各リクエストとその結果は、セキュリティ タイムラインの Guest sandbox の行になります。

カーネル・セントリー

カーネル・セントリーは小さな Linux カーネルモジュールで、VM のカーネルの内側から、そこで起きていることを報告します。報告は、エージェントがプロセスを殺しても黙らせられない専用の経路で Mac に届きます:

  • プログラムの起動;
  • 接続と、それぞれの背後にあるプロセスの連鎖;
  • 権限の変更;
  • モジュールと BPF の読み込み;
  • ゲストサンドボックスが拒否したすべて。

セントリーが起動すると、カーネルはロックされ、VM の root でさえ干渉するコードを読み込めなくなります。

セントリーがあるから、次のことが可能になります:

  • ネットワーク・リネージ — どのプロンプト、どのツール呼び出し、どのプロセスが各接続を行ったか。
  • タイムラインと、Sandbox ドロワーの Files タブに表示される サンドボックスの拒否。
  • 改ざんの検出 — セントリーの番号付きストリームの欠落、無効化されたプローブ、偽造された再接続、署名のないモジュールの読み込み、引き下げられたロックダウンは、赤で tampering suspected として示され、エージェント・ウォッチドッグに伝わります。
  • Enforce binaries のための バイナリの身元。

モードは 2 つあり、Kernel sentry カードで選びます:

モード起動時セントリーを読み込めないとき
Best effortセントリーはバックグラウンドで読み込まれ、セッションはそれを待ちません。マシンはセントリーなしで動き、カードが理由を示します。
Requiredセントリーが落ち着くまで、VM の中では何も動きません。カーネルはさらに厳しくロックされ、そのため bpftrace や perf のようなカーネルトレースツールも使えません。VM が理由を説明すれば(たとえば、そのカーネル用のモジュールが存在しない)、マシンは警告付きでセントリーなしに起動します。説明もなく一度も接続しないセントリーは、改ざんとして扱われます。

組織は最低限のモードを必須にできます。その場合、マシンは二つのうち厳しいほうで動きます。

オンデマンドのモジュール

カーネルモジュールは、それがビルドされたまさにそのカーネルにしか読み込めず、マシンはいつでも apt upgrade で新しい Ubuntu カーネルに移れます。そのため、モジュールはアプリに同梱されていません。Bromure は毎日すべての Ubuntu カーネル向けにモジュールをビルドし、dl.bromure.io で公開します。カタログと各モジュールには署名があり、Bromure は署名、チェックサム、そしてカタログが手元のものより古くないことを確かめます。

  • 起動時に、Bromure はマシンが使っていると分かっているカーネル向けのモジュールを取得し、各起動の前に用意します。
  • Bromure がまだ見たことのないカーネルで VM が起動すると、VM が問い合わせ、Bromure がモジュールを取得して数秒で渡します。
  • そのカーネル用のモジュールがまだないときは、すぐに VM に伝えられ、カードに Couldn't start: no module published for カーネル yet と表示されます。1 日後にもう一度試すか、前のカーネルで起動してください。

ダウンロードしたモジュールは ~/Library/Application Support/BromureAC/sentry-modules/ に保存されます。

Sandbox ドロワー

マシンのウインドウの上に開いた Sandbox ドロワー。Sandbox という題名、Web app · OpenShell + Sentry、Network・Files・Proposals のタブ、api.stripe.com:443 や pypi.org:443 などのブロックされた宛先(それぞれ回数と時刻、Allow ボタン、閉じる × 付き)、そして下部の Sandbox Policy… ボタン。

どのマシンのウインドウにも、ツールバーに盾のボタンがあります(「Sandbox: what it blocked, ready to allow」)。押すと、ステージの上に Sandbox ドロワー が開きます。⌃⌘N を押すか、表示 › Toggle Sandbox Drawer を選んでも開けます。ボタンの赤いバッジは、最後に見てからブロックされた宛先の数です。ドロワーには、マシンのサンドボックスが直近 2 時間に拒否したものが、許可できる状態で並びます:

タブエンジン内容
Network(ファイアウォールでは Blocked)両方ブロックされた各宛先と、試みたプログラム(分かれば)、回数、時刻。Allow はそのホストとポートのルールを追加します。ファイアウォールでは 常に、15 分間、1 時間、ワークスペースが停止するまで を選べます。OpenShell で Enforce binaries がオンなら、ルールは試みたプログラムを名指しします。
FilesOpenShell(filesystem_policy あり)ファイルシステムのサンドボックスが拒否したもの。フォルダごとにまとめられ、操作とファイルが示されます。Allow はフォルダを読み取り専用で、または Read and write で、あるいはそのファイルだけを追加します。ファイルへのアクセスは次の起動時に変わるので、再起動 カードが出ます。
ProposalsOpenShellパッケージのリクエスト(Install / Reject)と、ポリシーアドバイザーがあなたの判断を待っているルール(Approve / Reject)。
Temporaryファイアウォール期間を限ってオンになっているルールと、その終了時刻、そして End。

ドロワーから追加したルールはマシンに保存され、すぐに適用されます。ほかの編集と同じく、組織の境界と照合されます。下部の Sandbox Policy… は、マシンの設定を開きます。

ポリシーアドバイザー

壁にぶつかったエージェントは、たいてい自分に何が必要だったかを正確に知っています。OpenShell のもとでは、それを求めることができます:リクエストがブロックされると、エージェントはそれを許可する最も狭いルールを OpenShell のアドバイザー API である http://policy.local に提案し、あなたの判断を待てます。受け取った 403 がその方法を教えます。エージェントに何をさせるかは、サンドボックスポリシー › Policy advisor › Agent proposals で選びます:

モード起きること
Off(既定)エージェントはルールを提案できません。ブロックされた接続は、引き続きあなた向けの提案として下書きされます。
Ask me各提案は、あなたが Approve するか Reject するまで、Sandbox ドロワーと Policy advisor カードで待ちます。却下の理由はエージェントに送り返されます。
Approve if risk-freeリスクの指摘がない提案はすぐに承認されます。マシンが認証情報を持つホストに届く提案、そこにメソッドを追加する提案、ワイルドカード・プライベートアドレス・データベースのポート・高番ポートを使う提案は、常にあなたを待ちます。組織の境界を超えてしまう提案も同様です。

エージェントが提案できるのは rest か websocket のルールだけで、tls: skip は決して提案できません。承認されたルールはポリシーに追加され、即時に適用され、ポリシーの改訂履歴に残ります。すべての提案と判定は、セキュリティ タイムラインの Firewall の行になります。

エージェントに伝える:ポリシーステアリング

「connection refused」や「permission denied」しか見えないエージェントは、再試行し、それから別の道を探しがちです。外から見ると、エージェントが暴走しているように見えます。Tell the agent when policy blocks it(ガードレール › 保護機能にあり、OpenShell マシンでは既定でオン)があれば、エージェントは会話の中で、何がなぜブロックされたかを伝えられます。たとえば:

[Bromure policy] This workspace's network policy blocked connecting to api.stripe.com:443 — no network policy allows api.stripe.com:443. … This is a deliberate restriction, not a fault: don't retry it or reach the same thing another way … If your task needs it, stop and tell the user what you need and why so they can decide.

  • Claude Code は、ブロックに当たったコマンドの直後、ターンの途中で通知を受け取ります。
  • Codex、Grok、Kimi、Oh My Pi には、ターンが終わった時点で入力されます。
  • 通知は、カーネル・セントリーのプロセス連鎖を使って、ブロックされた接続やファイルアクセスを行ったプロセスのエージェントに届きます。
  • どのエージェントか Bromure に分からないときは、ネットワークのブロックはマシンのすべてのエージェントに、ファイルのブロックはエージェントが 1 つだけの場合に限りそのエージェントに伝えられます。
  • 同じブロックは 5 分に 1 回しか伝えられず、1 つのエージェントが受け取る通知は 1 分に最大 5 件です。エージェント自身のバックグラウンド通信と、よくあるテレメトリのホストは、決して報告されません。

通知の中の VM から来た値(ホストやパス)はデータとして引用されるので、プログラムがブロックを利用してエージェントに言葉を吹き込むことはできません。

エージェント・ウォッチドッグ

ウォッチドッグは VM の外から、セッションを全体として見ます:

  • ブロックの集中;
  • 場違いな認証情報;
  • セントリーの改ざんの兆候;
  • 失敗したサンドボックス;
  • プロンプトインジェクション;
  • セッションが落ち着いた後の新しい宛先;
  • 基準を大きく上回る送信量。

1 分以内にしきい値を超えると、指摘を記録するか(Alert)、VM のネットワークを切って一時停止し、どうするかをあなたに尋ねます(Quarantine)。ガードレール › エージェント・ウォッチドッグを参照してください。既定ではオフです。オフでも、改ざんの警報はセキュリティ タイムラインと OCSF ログに記録されます。

組織の境界

組織は 境界、つまりどのマシンの OpenShell ポリシーでも許可できる上限を設定できます。境界は、登録済みの Mac では bromure.io から届き(10 分ごとに更新され、オフライン用にキャッシュされます)、またはこの Mac 上のファイルから読み込まれます(サンドボックスポリシー › Governance › Organization boundary)。ポリシーを変える保存はすべて、設定、Sandbox ドロワー、ポリシーアドバイザー、API のどこからでも、これと照合されます。Bromure は、NVIDIA の openshell-prover がインストールされていればそれを、なければ独自のチェックを使います。

  • エディタでは、入力に合わせて緑か赤の判定が表示され(「within boundary」、または許可してしまうものの例を添えた「exceeds boundary: …」)、ポリシーが収まるまで 保存 は待ちます。
  • ほかの場所では、境界の外の保存は「outside the organization boundary — …」で拒否されます。
  • 以前に保存され、もう収まらないポリシーはフェイルクローズします:Bromure 自身が追加するルールの宛先だけに届きます。

同じ経路で、組織は次のこともできます:

  • 新しい OpenShell マシンの既定ポリシーを決める;
  • Enforce binaries や厳格な認証情報を必須にする;
  • カーネル・セントリーの最低限のモードを決める;
  • ポリシーアドバイザーのモードに上限を設ける;
  • エージェントの推論をネットワーク・リネージとともにアップロードするよう求める。

エンタープライズを参照してください。

ポリシーを変える保存は、変更の出どころとともに、そのポリシーの Revision history にも残ります。復元 でどのバージョンにも戻せます。

関連する章