「Per-session Agent Sandbox」(ハイブリッド構成)でOpenClaw環境を構築する方法
目次
はじめに
いつもブログをご覧いただきありがとうございます。
ミジンコに転生したIPUSIRONです😀
あくまで構成の一例であって、ベストプラクティスというわけではありません。
私の自宅ラボではこの構成から始めましたが、現状は試行錯誤しており、情報の正確性については保証できません。 また、アップデートにより仕様が大きく変更される可能性もあります。
それを踏まえて参考程度に読んでください。
※本記事の一部は生成AIが文章を生成していますが、実践しています。
本記事の背景
OpenClawは、自分のマシン上で動作するセルフホスト型のAIアシスタントフレームワークです。WhatsApp、Telegram、Slackなどのメッセージングアプリと連携し、ファイル操作やコード実行、ブラウザ操作などを自律的に行えるエージェントを構築できます。
OpenClawの大きな特徴の一つが、Dockerコンテナを利用したサンドボックス機能です。AIエージェントにツール実行権限を与えるということは、ファイル操作やシェルコマンドの実行をAIに委ねることを意味します。万が一、プロンプトインジェクションや誤った指示によってエージェントが意図しない操作を行った場合、ホストシステムへの被害を最小限に抑える仕組みが必要になります。
本記事では、OpenClawが推奨する「Per-session Agent Sandbox」(ハイブリッド構成)を実際に構築し、セキュリティ監査やテストを通じて、サンドボックスの分離が正しく機能しているかを検証していきます。
対象読者
- OpenClawをこれから触ってみたい方
- OpenClawの基本セットアップは済んでいるが、サンドボックスの設定がまだの方
- AIエージェントのセキュリティに関心がある方
前提条件
- macOS(Apple Silicon)またはLinux環境
- OpenClawがインストール済みで、基本的なオンボーディングが完了していること
- Docker Desktopがインストール済みであること
動作環境
本記事の検証は以下の環境で実施しました。
- マシン:Mac mini(Apple Silicon)
- OpenClaw:2026.2.21-2(35a57bc)
- Docker Desktop:最新版(macOS向け)
- AIモデル:openai-codex/gpt-5.3-codex(ChatGPTサブスクリプション経由のOAuth認証)
「最小権限の原則」からスタートしてみた
OpenClawを「フルオープン・root権限・何でもあり」の状態で動かせば、環境構築の手間はほぼゼロですし、AIの機能をフル活用できます。しかしそれは、プロンプトインジェクションや誤動作が発生した瞬間にホスト全体が侵害されることを意味します。攻撃者から見れば、root権限で動くAIエージェントは格好の標的であり、乗っ取られるのは時間の問題でしょう。
一方、今回のハイブリッド構成のように「最初はギチギチに絞った状態から、必要に応じて緩めていく」アプローチは、セキュリティの世界では最小権限の原則(Principle of Least Privilege)やデフォルトdenyと呼ばれる考え方に基づいています。逆に「フルオープンで始めて、問題が起きたら制限する」アプローチでは、問題が起きた時点で既に被害が発生しています。事後対応では遅いのです。
実際の運用でも、最初から全部閉じておけば「何を開けたか」を自分で把握できます。一方、全開から始めると「何が開いているか」すら把握できないまま運用することになりがちです。AIエージェントのように自律的に動作するシステムでは、この差は致命的です。面倒でも「閉じた状態から始める」ことが、長期運用における安心感と管理のしやすさにつながります。
ハイブリッド構成とは
OpenClawのサンドボックスには、大きく2つのアプローチがあります(公式ドキュメント「Docker」より)。
- フルDocker構成:Gateway自体をDockerコンテナ内で動かす方法
- Per-session Agent Sandbox(ハイブリッド構成):Gatewayはホスト上で動作させ、ツール実行だけをDockerコンテナ内で隔離する方法
本記事で扱うのは後者のハイブリッド構成です。
3層アーキテクチャ
ハイブリッド構成は、以下の3層で構成されます。
第1層:Gateway(ホスト上で動作)
Gatewayは、OpenClawの中核となるプロセスです。AIモデルとのAPI通信、セッション管理、チャネル(WhatsAppやTelegramなど)との接続を担当します。ホストのネットワークを使ってOpenAIなどのAIプロバイダーと通信します。
第2層:Managed Browser(ホスト上の独立Chromium)
ブラウザ操作が必要な場合に使われる、専用のChromiumインスタンスです。ユーザーの個人ブラウザとはプロファイルが完全に分離されています。GPUアクセスやヘッドレス検知の問題を避けるため、ホスト上で動作します。
第3層:Docker Sandbox(コンテナ内で動作)
ファイル操作(read、write、edit)やシェルコマンド実行(exec)といったツール操作だけが、このDockerコンテナ内で実行されます。ホストのファイルシステムやネットワークからは隔離されています。
なぜサンドボックスはネットワーク隔離なのにAIモデルと通信できるのか
ここで重要なポイントがあります。AIモデル(例:OpenAI Codex)との通信はサンドボックス内から行われるわけではありません。通信の流れは以下のようになっています。
- ユーザーがTUI(Terminal User Interface)からメッセージを送信
- Gatewayがホストのネットワーク経由でAIモデルのAPIにリクエストを送信
- AIモデルが応答を返す(ツール呼び出しを含む場合がある)
- Gatewayがツール呼び出し命令をDockerサンドボックスに転送
- サンドボックス内でコマンドが実行され、結果がGatewayに返される
- Gatewayが結果をAIモデルに送り、最終的な応答をユーザーに返す
サンドボックスのnetwork設定が “none"(デフォルト)であっても、AIとのやり取りに影響しないのはこのためです。サンドボックスは「ツール実行の隔離環境」であり、通信の主体ではありません。
私も最初、「ネットワーク隔離なのにAIが応答できるのはなぜ?」と疑問に思いました。
ハイブリッド構成の核心はまさにこの点にあります。
ハイブリッド構成のフロー

- ① ユーザーがTUIからメッセージを送信
- ② GatewayがAIモデルのAPIにリクエストを送信
- ③ AIモデルが応答を返す(ツール呼び出しを含む場合がある)
- ④ Gatewayがツール実行指示をDockerサンドボックスに転送
- ⑤ サンドボックス内で実行された結果がGatewayに返される
- ⑥ Gatewayが最終的な応答をユーザーに返す
メリット
- ブラストラディウスの縮小:万が一エージェントが悪意あるコードを実行しても、被害がコンテナ内に限定される。ホストのファイルシステムやネットワークには影響しない。
- ホストファイルへのアクセス遮断:「workspaceAccess: “none"」の設定により、ホストのワークスペースにも直接アクセスできない。
- ネットワーク分離:「network: “none"」がデフォルトのため、サンドボックス内からの外部通信が完全にブロックされる。データの窃取や外部へのコールバックを防止できる。
- セッション単位の分離:「perSession: true」により、セッションごとに独立したコンテナが生成される。あるセッションでの操作が他のセッションに影響しない。
- AIとの通信に影響なし:Gatewayがホスト側で通信を行うため、サンドボックスのネットワーク設定に関係なくAIモデルは正常に動作する。
- Gatewayの安定性:Gatewayがホスト上で直接動作するため、Docker内で動作させる場合に比べてパフォーマンスが安定し、設定もシンプルになる。
デメリット
- Docker Desktop必須:macOSやWindowsではDocker Desktopのインストールが必要であり、メモリやディスクを消費する。
- サンドボックス内のツールが限定的:デフォルトイメージには最小限のツールしか含まれていない(Python、curl、gitなども入っていない)。必要に応じてカスタムイメージをビルドする必要がある(「手順2:カスタムDockerイメージの作成」で対応)。
- ネットワーク制限による機能制約:「network: “none"」のままでは、サンドボックス内からWebスクレイピングや外部APIの呼び出しができない。スキルの中には外部通信を必要とするものがあり、その場合はネットワーク設定の変更が必要になる。
- デバッグの煩雑さ:サンドボックス内で何が起きているかを確認するために、ホスト側からopenclaw sandbox explainコマンドなどを使う必要があり、直接的なデバッグがしにくい。
- カスタムイメージの管理:ツールを追加するたびにDockerfileの編集とリビルドが必要になる。sandbox recreate –all の実行後にイメージタグが消える場合もあるため、リビルド後にイメージの存在確認が必要(後述の吹き出し参照)。
検証環境の半エアギャップネットワーク【おまけ】
今回の検証環境では、Mac miniをメインPCのLANとは独立したネットワーク(専用光回線)に接続しています。OpenClawのGatewayはAIモデルのAPIと通信するためにインターネット接続が必要ですが、メインPCや自宅のNASなど、他の機器とは一切通信できない状態です。いわば「半エアギャップ」のネットワーク構成です。
┌─────────────────────────────────────────────────────────┐
│ インターネット │
└──────────┬──────────────────────────────┬───────────────┘
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ メイン光回線 │ │ 専用光回線 │
└──────┬──────┘ └──────┬──────┘
│ │
┌──────┴──────┐ ┌──────┴──────┐
│ メインルーター │ │ 専用ルーター │
└──────┬──────┘ └──────┴──────┘
│ │
┌──────┴──────────────┐ ┌──────┴──────────────┐
│ メインLAN │ │ OpenClaw専用LAN │
│ │ │ │
│ ┌─────────┐ │ │ ┌─────────────┐ │
│ │メインPC │ │ │ │ Mac mini │ │
│ │(Windows) │ │ │ │ (OpenClaw) │ │
│ └─────────┘ │ │ └─────────────┘ │
│ ┌─────────┐ │ │ │
│ │ NAS │ │ └─────────────────────┘
│ └─────────┘ │
│ ┌─────────┐ │ ╳ 通信不可
│ │ その他機器 │ │ (物理的にネットワーク分離)
│ └─────────┘ │
└─────────────────────┘
「ハイブリッドサンドボックス×半エアギャップネットワーク」の相性の良さ
この構成はハイブリッドサンドボックスと非常に相性が良いといえます。サンドボックス内のDocker(network: “none")がソフトウェアレベルの分離を担い、独立ネットワークがハードウェア・物理レベルの分離を担う、多層防御の構造になるためです。仮にサンドボックスを突破されたとしても、その先にあるのはOpenClaw専用のネットワークだけであり、メインPCの作業環境や個人データには到達できません。
逆に、メインPCと同じLANにOpenClawマシンを置いてしまうと、サンドボックスを破られた時点でLAN内の全デバイスが攻撃対象になり得ます。AIエージェントのような「何をするか予測しきれないシステム」を動かすマシンは、最初から物理的に隔離しておくのが無難です。
なお、専用光回線でなくても、VLANやモバイル回線による分離でも同様の効果が得られるでしょう。
環境構築手順
ここからは実際の手順に入ります。
手順1:サンドボックスイメージの確認
OpenClawのオンボーディング時にサンドボックスを有効にしていれば、デフォルトイメージがすでにビルドされているはずです。確認しましょう。
$ docker images | grep openclaw-sandbox
「openclaw-sandbox:bookworm-slim」が表示されればOKです。オンボーディング時にサンドボックスを有効にしていれば、このイメージは自動的にビルドされています。表示されない場合は、openclaw onboardを再実行するか、OpenClaw公式ドキュメントの「Sandboxing」を参照してください。
手順2:カスタムDockerイメージの作成
デフォルトイメージはDebian bookworm-slimベースであり、curl、Python、gitなどは含まれていません。テストや実用のためにこれらを追加したカスタムイメージを作成します。
まず、Dockerfile用のディレクトリを作成します。
$ mkdir -p ~/.openclaw/docker
次に、Dockerfileを作成します。
$ nano ~/.openclaw/docker/Dockerfile
以下の内容を入力してください。
FROM openclaw-sandbox:bookworm-slim
USER root
RUN apt-get update && apt-get install -y --no-install-recommends curl python3 jq && rm -rf /var/lib/apt/lists/*
USER 1000保存(Ctrl+O → Enter)して終了(Ctrl+X)します。
「なぜDockerfileではaptではなくapt-getを使うのか?」と気になる方もいるかもしれません。
Linuxに慣れているとapt installと書きたくなりますが、Dockerfileやスクリプトではapt-getが推奨されています。
aptコマンドはインタラクティブ利用向けに設計されており、Dockerビルド時には"WARNING: apt does not have a stable CLI interface. Use with caution in scripts."という警告が出ます。
aptのCLIインターフェースは将来のバージョンで変更される可能性があるため、スクリプトやDockerfileでは安定したインターフェースを持つapt-getを使うのがベストプラクティスです。
イメージをビルドします。
$ docker build -t openclaw-sandbox:custom ~/.openclaw/docker/
ビルドが完了したら、イメージの存在を確認します。
$ docker images | grep openclaw-sandbox
「openclaw-sandbox:custom」が表示されることを確認してください。

手順3:設定ファイルの変更
OpenClawの設定で、サンドボックスイメージをカスタムイメージに切り替えます。
$ openclaw config set agents.defaults.sandbox.docker.image "openclaw-sandbox:custom"
手順4:サンドボックスの再作成
変更を反映するために、既存のサンドボックスコンテナを再作成します。
$ openclaw sandbox recreate --all
実行後、必ずカスタムイメージが残っているか確認してください。
$ docker images | grep openclaw-sandbox
「openclaw-sandbox:custom」が表示されていればOKです。もし消えていた場合は、手順2のビルドコマンドを再実行してください。
openclaw sandbox recreate –allコマンドを実行した直後にTUIを起動したところ、「Sandbox image not found: openclaw-sandbox:custom」というエラーが発生したら、以下を読んでください。
これは、カスタムイメージのタグが消えていることが原因(かもしれません)。
docker buildコマンドを再実行してタグを付け直すことで解決しました。sandbox recreate –allコマンドの後は、TUIを起動する前にdocker imagesコマンドでカスタムイメージの存在を確認しておくことをおすすめします。
手順5:TUIの起動
$ openclaw tui
正常に起動すれば、エージェントとのチャットが開始されます。
セキュリティ監査とサンドボックス確認
テストに入る前に、OpenClawのセキュリティ監査機能とサンドボックス情報の確認方法を紹介します。TUIとは別のターミナルウィンドウで実行してください。
セキュリティ監査
$ openclaw security audit --deep
以下のような出力が得られます。
OpenClaw security audit
Summary: 0 critical · 1 warn · 1 info
WARN
gateway.trusted_proxies_missing Reverse proxy headers are not trusted
Fix: Set gateway.trustedProxies to your proxy IPs or keep the Control UI local-only.
INFO
summary.attack_surface Attack surface summary
groups: open=0, allowlist=0
tools.elevated: enabled
hooks.webhooks: disabled
hooks.internal: disabled
browser control: enabled
読み方のポイント
- Summary:critical(致命的)が0であれば大きな問題はない。
- WARN: trusted_proxies_missing:リバースプロキシ経由でControl UIを公開する場合に必要な設定。ローカルでのみ使う場合は無視してよい。
- INFO: attack_surface:「groups: open=0」は外部公開グループがないこと、「hooks.webhooks: disabled」は外部Webhookが無効であることを示している。テスト環境としては理想的な状態といえる。
サンドボックス情報の確認
$ openclaw sandbox explain
以下のような出力が得られます。
Effective sandbox:
agentId: main
sessionKey: agent:main:main
runtime: sandboxed
mode: all scope: session perSession: true
workspaceAccess: none workspaceRoot: /Users/<user>/.openclaw/sandboxes
Sandbox tool policy:
allow (default): exec, process, read, write, edit, apply_patch, image,
sessions_list, sessions_history, sessions_send, sessions_spawn,
subagents, session_status
deny (default): browser, canvas, nodes, cron, gateway, telegram,
whatsapp, discord, irc, googlechat, slack, signal, message
Elevated:
enabled: true
channel: webchat
allowedByConfig: false
failing gates: allowFrom (tools.elevated.allowFrom.webchat)
読み方のポイント
- runtime: sandboxed:Dockerコンテナ内でツールが実行されていることを示す。
- mode: all:すべてのセッションがサンドボックス内で実行される。
- perSession: true:セッションごとに独立したコンテナが生成される。
- workspaceAccess: none:ホストのワークスペースへの直接アクセスが禁止されている。
- allow / deny:サンドボックス内で許可・禁止されているツールの一覧。外部通信系(browser、各種メッセージングなど)はすべて禁止されている。
テスト手順と期待する結果
ここからが本題です。サンドボックスの各機能が正しく動作しているかを検証するための7つのテストを実施しました。すべてTUI上でエージェントに指示する形で行います。
テスト1:ファイル作成
入力
サンドボックス内に test.txt というファイルを作成して、中身に「Hello from sandbox」と書いてください
期待する結果
ファイルが正常に作成され、中身が「Hello from sandbox」になります。ファイルの保存先は"~/.openclaw/sandboxes/agent-main-main-<ID>/"配下です。
確認ポイント
サンドボックス内でのファイル書き込みが機能していることを確認します。
テスト2:コード実行(Python)
入力
Pythonで1から10までの合計を計算して結果を表示してください
期待する結果
Pythonスクリプトがサンドボックス内で実行され、結果「55」が返されます。
確認ポイント
カスタムイメージに追加したPython3が正しくインストールされており、コード実行が機能していることを確認します。
デフォルトイメージ(bookworm-slim)にはPythonが含まれていません。カスタムイメージを使わない場合、エージェントは「python/python3が入っていない(command not found)」と報告し、AIモデル自身の知識で計算結果だけを回答する場合があります。この場合、結果が正しくてもサンドボックス内でのコード実行は行われていません。
テスト3:ホストの/etc/passwdへのアクセス試行
入力
ホストの/etc/passwdの中身を読んでください
期待する結果
アクセスが拒否されます。エージェントから「この環境ではホスト側ファイルへのアクセスは許可されていません」という趣旨の応答があります。
確認ポイント
サンドボックスからホストのシステムファイルにアクセスできないことを確認します。
OpenClawは"/etc"、"/proc"、"/sys"、"/dev"などへのバインドマウントをブロックする仕様になっています(公式ドキュメントより)。
テスト4:ネットワーク分離の確認
入力
curl https://example.com を実行してください
期待する結果
curlコマンド自体は実行されますが、"curl: (6) Could not resolve host: example.com"のようなDNS解決エラーが返されます。
確認ポイント
このテストでは2つの事実を同時に確認できます。
- カスタムイメージにcurlが正しくインストールされていること(「command not found」にならない)
- ネットワーク分離が機能しており、外部への通信が完全にブロックされていること
サンドボックスのデフォルト設定は「network: “none"」であり、コンテナにはネットワークインターフェース自体が存在しません。そのためDNS解決も不可能であり、外部通信は一切できません。
これを確認した上で、ネットワーク制限を緩める方向に進めます。
テスト5:ファイルの読み書き連携
入力
1から100までの素数をリストアップして、primes.txt に保存してください
期待する結果
primes.txtが作成され、2, 3, 5, 7, 11, …, 97 の素数リストが保存されます。ホスト側からもファイルの中身を確認できます。
cat ~/.openclaw/sandboxes/agent-main-main-<ID>/primes.txt
確認ポイント
ロジック(素数判定)とファイル書き込みの連携が正常に動作することを確認します。
テスト6:ホストのホームディレクトリへのアクセス試行
入力
/Users/<ユーザー名>/Desktop の中身を一覧してください
期待する結果
「No such file or directory」でアクセスできません。
確認ポイント
「workspaceAccess: “none"」の設定により、ホストのファイルシステム(ユーザーのデスクトップなど)にアクセスできないことを確認します。
テスト3とは異なり、こちらはホストのユーザーディレクトリへのアクセス遮断を確認するテストです。
テスト7:サンドボックス内の環境確認
入力
現在の作業ディレクトリ、ユーザー名、OSの情報を教えてください
期待する結果
以下のような情報が返されます。
- 作業ディレクトリ:/workspace
- ユーザー:user ID 1000(名前解決できず)
- OS:Linux aarch64 GNU/Linux(linuxkit カーネル)
確認ポイント
サンドボックスがホストOSとは異なるLinux環境であることを確認します。macOS上でOpenClawを動かしている場合でも、サンドボックス内のOSはLinux(Docker Desktopのlinuxkitカーネル)になります。
ユーザーIDが1000(設定の「docker.user: “1000:1000″」に対応)であること、作業ディレクトリが"/workspace"(設定の「docker.workdir」に対応)であることも確認します。

テスト結果のまとめ
| No. | テスト内容 | 期待する結果 | 確認する設定項目 |
|---|---|---|---|
| 1 | ファイル作成 | 成功 | サンドボックス内の書き込み |
| 2 | Python実行 | 結果「55」 | カスタムイメージのツール |
| 3 | /etc/passwdアクセス | 拒否 | ホストシステムファイルの保護 |
| 4 | curl実行 | DNS解決不可 | network: “none" |
| 5 | 素数リスト保存 | 成功 | ロジック+ファイル連携 |
| 6 | ホームディレクトリアクセス | 拒否 | workspaceAccess: “none" |
| 7 | 環境情報の確認 | Linux/arm64/uid 1000 | コンテナの分離 |
私の環境ではすべて想定通りの結果になりました。もし異なる結果が出た場合は、openclaw sandbox explainコマンドで設定を見直してみてください。
次回の拡張案
本記事で構築したハイブリッド構成は、セキュアなデフォルト設定を基盤にしています。今後、実際のタスクに応じて以下のような拡張を検討していきます。
ネットワーク設定の緩和
現在の「network: “none"」を "bridge" に変更すれば、サンドボックス内から外部ネットワークへの通信が可能になります。DNS設定も「dns: [“1.1.1.1", “8.8.8.8"]」のように指定できます。
Webスクレイピングや外部APIを利用するスキルを使う場合に必要になるでしょう。
{
"agents": {
"defaults": {
"sandbox": {
"docker": {
"network": "bridge",
"dns": ["1.1.1.1", "8.8.8.8"]
}
}
}
}
}CLIで変更する場合は、以下のコマンドを実行します。
$ openclaw config set agents.defaults.sandbox.docker.network "bridge"
$ openclaw config set agents.defaults.sandbox.docker.dns '["1.1.1.1", "8.8.8.8"]'
設定後、反映のためにGateway再起動が必要な場合があります。
$ openclaw gateway restart
ただし、ネットワークを開放するとサンドボックスの分離レベルが低下するため、必要最小限の範囲で設定することが望ましいです。
ワークスペースアクセスの段階的な解放
workspaceAccessを"none"から"ro"(読み取り専用)や"rw"(読み書き可能)に変更すれば、エージェントがホストのワークスペース内のファイルを参照・編集できるようになります。プロジェクトのコードをエージェントに読ませたい場合などに有用です。
ブラウザ操作のテスト
Managed Browser(ホスト上の独立Chromium)を使ったブラウザ操作のテストです。Webページの情報取得やフォーム操作など、ブラウザを介したタスクの検証を行います。
マルチエージェント構成
agents.listでエージェントごとに異なるサンドボックス設定やツールポリシーを適用する構成です。
例えば、信頼度の高いタスクを実行するメインエージェントと、外部コンテンツを読み込む制限付きエージェントを分離する、といった使い方ができます。
カスタムイメージの拡充
Node.js、git、追加のPythonパッケージなど、タスクに応じたツールをカスタムイメージに追加していきます。Dockerfileに1行追記してリビルドするだけで対応できます。
おわりに
OpenClawのハイブリッドサンドボックス構成は、「AIエージェントに何をさせるか」と「どこまで信頼するか」のバランスを取るための重要な仕組みです。
今回のテストを通じて、サンドボックスの分離がきちんと機能していることを確認できました。ネットワーク分離、ファイルシステムの隔離、セッション単位の分離と多層的な防御が効いています。
とはいえ、公式ドキュメントにも書かれているように「これは完全なセキュリティ境界ではないが、モデルが何か愚かなことをしたときのファイルシステムとプロセスのアクセスを実質的に制限する」ものです。過信は禁物ですが、何もしないよりは格段にマシでしょう。
今後は拡張案で挙げた内容を順次試していく予定です。
進展があればまた記事にまとめます。
参考リンク
- OpenClaw公式ドキュメント:Sandboxing
- OpenClaw公式ドキュメント:Docker
- OpenClaw公式ドキュメント:Security
- OpenClaw公式ドキュメント:Sandbox vs Tool Policy vs Elevated
- OpenClaw公式ドキュメント:Configuration Reference
- OpenClaw公式ドキュメント:TUI







