Claude Code と Claude Agent SDK は、コードを実行し、ファイルを読み書きし、外部サービスに接続します。あらかじめ決まった処理だけをたどる従来のソフトウェアと違い、行動は文脈から動的に決まるため、読み込んだファイル・Web ページ・ユーザー入力の内容に影響されることがあります(プロンプトインジェクション)。この記事では公式ドキュメント「Securely deploying AI agents」に沿って、このリスクを下げるための隔離・認証情報の管理・ネットワーク制御の選択肢を整理します。ノートPCで1人が使う場合と、顧客データを扱うマルチテナント環境とでは必要な守りが違うので、公式も「状況に合うものを選ぶ」前提で、組み込み機能から本番向けの堅い構成までを並べています。
脅威モデルと組み込みのセキュリティ機能
エージェントが意図しない行動をとる原因として、公式は2つを挙げています。処理する内容に埋め込まれた指示(プロンプトインジェクション)と、モデル自身の誤りです。たとえばリポジトリの README に不自然な指示が書かれていれば、運用者が想定しない形でそれを行動に取り込むかもしれません。Claude のモデルはこうした攻撃に耐えるよう設計されていますが、それでも多層防御は有効です。悪意あるファイルが「顧客データを外部サーバーへ送れ」と指示しても、ネットワーク制御があればそのリクエスト自体を止められます。
Claude Code には、次のセキュリティ機能が最初から入っています。
- 権限システム: ツールや bash コマンドごとに「許可・拒否・確認を求める」を設定できます。glob パターンで「npm コマンドはすべて許可」「sudo を含むコマンドは拒否」のようなルールを書け、組織全体に効くポリシーも設定できます(「Claude Code の設定と権限」参照)。
- 権限判定のためのコマンド解析: bash コマンドは実行前に構文木(AST)へ解析され、権限ルールと照合されます。きれいに解析できないコマンドや許可ルールに合わないコマンドは明示的な承認が必要で、
evalなど一部の構文は許可ルールに関係なく常に承認が必要です。ただしこれは権限の関門であってサンドボックスではありません。rm・rmdirの重要パス確認や保護パスの一覧といった組み込みの安全確認を除けば、対象のパスや結果からコマンドの危険性を推測はしません。 - Web 検索結果の要約: 検索結果は生の内容をそのまま文脈に入れず要約してから渡すので、悪意ある Web コンテンツからの注入リスクが下がります。
- サンドボックスモード: bash コマンドを、ファイルシステムとネットワークへのアクセスを制限した環境で実行できます(「Claude Code の隔離環境を選ぶ」参照)。
セキュリティの3原則
既定の機能より堅くしたい場合、公式は次の3つの考え方を軸に選択肢を並べています。
セキュリティ境界: 信頼度の違う部品を境界で分けます。高いセキュリティが要る構成では、認証情報のような重要な資源をエージェントのいる境界の外に置きます。エージェントの環境で何か起きても、境界の外の資源は守られます。たとえば API キーを直接渡す代わりに、エージェントの環境の外でキーをリクエストに付け足すプロキシを動かせば、エージェントは API を呼べてもキー自体は見えません。マルチテナント構成や信頼できない内容を扱う場合に役立つパターンです。
最小権限: 必要に応じて、エージェントをそのタスクに要る能力だけに絞ります。
| 資源 | 制限の方法 |
|---|---|
| ファイルシステム | 必要なディレクトリだけをマウントし、できれば読み取り専用にする |
| ネットワーク | プロキシ経由で特定の接続先だけに絞る |
| 認証情報 | 直接見せず、プロキシで注入する |
| システムの能力 | コンテナで Linux capabilities を落とす |
多層防御: コンテナによる隔離、ネットワーク制限、ファイルシステムの制御、プロキシでのリクエスト検証を重ねます。どう組み合わせるかは、脅威モデルと運用上の要件で決まります。
隔離技術を比較する
どの構成でも、Claude Code(または Agent SDK のアプリ)は隔離境界の内側で動き、以降の制御はその境界の中から何にアクセスできるかを絞るものです。公式の比較は次のとおりです。
| 技術 | 隔離の強さ | 性能への負荷 | 複雑さ |
|---|---|---|---|
| Sandbox runtime | 良い(安全な既定値) | とても低い | 低い |
| コンテナ(Docker) | 設定次第 | 低い | 中 |
| gVisor | 非常に高い(正しく設定した場合) | 中〜高 | 中 |
| VM(Firecracker、QEMU) | 非常に高い(正しく設定した場合) | 高い | 中〜高 |
Sandbox runtime: Anthropic の sandbox-runtime は、コンテナを使わずに OS の機能でファイルシステムとネットワークを制限します。Linux では bubblewrap、macOS では sandbox-exec(Seatbelt プロファイル)を使い、ネットワークは内蔵のプロキシ経由に限定します。許可するドメインとパスは JSON の設定で指定します。導入は npm install @anthropic-ai/sandbox-runtime です。注意点として、VM と違ってホストのカーネルを共有するのでカーネルの脆弱性を突かれる余地が理論上はあり、またプロキシは TLS の中身を検査せずクライアントが示したホスト名でドメインを判定するため、ドメインフロンティングのような手法で許可リスト外へ届く可能性があります。それでも、個人開発や CI/CD の多くの用途では最小の手間で守りを大きく上げられる、と公式は位置づけています。
コンテナ: Linux の名前空間で、ファイルシステム・プロセスツリー・ネットワークを分けます(カーネルはホストと共有)。公式が示す堅めの設定例は次のとおりです。
docker run \
--cap-drop ALL \
--security-opt no-new-privileges \
--security-opt seccomp=/path/to/seccomp-profile.json \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--tmpfs /home/agent:rw,noexec,nosuid,size=500m \
--network none \
--memory 2g \
--cpus 2 \
--pids-limit 100 \
--user 1000:1000 \
-v /path/to/code:/workspace:ro \
-v /var/run/proxy.sock:/var/run/proxy.sock:ro \
agent-image
| オプション | 目的 |
|---|---|
--cap-drop ALL | NET_ADMIN や SYS_ADMIN など、権限昇格につながる Linux capabilities を外す |
--security-opt no-new-privileges | setuid バイナリ経由で権限を得るのを防ぐ |
--security-opt seccomp=... | 使えるシステムコールを制限する(Docker の既定で約44個をブロック。独自プロファイルでさらに絞れる) |
--read-only | ルートファイルシステムを書き換え不可にし、変更を残させない |
--tmpfs /tmp:... | コンテナ停止で消える書き込み用の一時ディレクトリ |
--network none | ネットワークインターフェースをすべて外す。外との通信はマウントした Unix ソケットだけ |
--memory 2g / --pids-limit 100 | メモリの使い果たしや fork 爆弾を防ぐ |
--user 1000:1000 | root 以外のユーザーで動かす |
-v ...:/workspace:ro | コードを読み取り専用でマウントする。~/.ssh・~/.aws・~/.config などはマウントしない |
-v .../proxy.sock:... | コンテナの外で動くプロキシにつながる Unix ソケット |
--network none にすると、外と話す道はマウントした Unix ソケットだけになり、その先のホスト側プロキシがドメインの許可リスト・認証情報の注入・通信のログを担います。sandbox-runtime と同じ構造で、プロンプトインジェクションでエージェントが乗っ取られても任意のサーバーにはデータを持ち出せません。さらに堅くするなら、コンテナの root を非特権のホストユーザーに対応させる --userns-remap(デーモン側の設定が必要)や、プロセス間通信を分ける --ipc private も使えます。
gVisor: 通常のコンテナではシステムコールがそのままホストカーネルに届きますが、gVisor はユーザー空間でシステムコールを受け止めて独自の互換層で処理します。悪意あるコードはまず gVisor の実装を破る必要があり、本物のカーネルに触れる範囲が小さくなります。Docker では runsc ランタイムを入れて /etc/docker/daemon.json に登録し、docker run --runtime=runsc agent-image で起動します。
{
"runtimes": {
"runsc": {
"path": "/usr/local/bin/runsc"
}
}
}
負荷の目安は、CPU 中心の計算はほぼ0%、単純なシステムコールは約2倍遅く、ファイルを大量に開閉する I/O 中心の処理では10〜200倍遅くなることもあります。マルチテナントや信頼できない内容を扱うなら、この負荷を払う価値があることが多いとされています。
仮想マシン: CPU の仮想化支援でハードウェアレベルの隔離を行い、VM ごとに自分のカーネルを持ちます。ただし VM だから自動的に gVisor より安全とは限らず、ハイパーバイザやデバイスエミュレーションの実装に左右されます。Firecracker は軽量な microVM 向けで、125ms 未満で起動し、メモリのオーバーヘッドは 5MiB 未満です。エージェントの VM には外向きのネットワークインターフェースを持たせず、vsock(仮想ソケット)経由でホストのプロキシに通信を集めます。
クラウドでは、これらに加えて、インターネットゲートウェイの無いプライベートサブネットに置く、ファイアウォール(AWS のセキュリティグループや GCP の VPC ファイアウォール)でプロキシ以外への外向き通信を止める、Envoy の credential_injector フィルタのようなプロキシで検証と認証情報の注入を行う、エージェントのサービスアカウントの IAM 権限を最小にする、プロキシで全通信を監査ログに残す、を組み合わせます。
プロキシで認証情報を渡す
エージェントは API・リポジトリ・クラウドサービスを使うために認証情報を必要としますが、認証情報そのものは見せたくありません。公式が推奨するのは、エージェントのセキュリティ境界の外でプロキシを動かし、外向きのリクエストに認証情報を付け足す形です。エージェントが実際の認証情報を見ない、プロキシで接続先の許可リストを強制できる、全リクエストを監査用に記録できる、認証情報を各エージェントに配らず1か所で保管できる、という利点があります。
Claude Code と Agent SDK をプロキシ経由にする方法は2つです。
# 方法1: Claude API へのサンプリングリクエストだけをプロキシへ送る
export ANTHROPIC_BASE_URL="http://localhost:8080"
# 方法2: HTTP 通信全体を標準の環境変数でプロキシへ送る
export HTTP_PROXY="http://localhost:8080"
export HTTPS_PROXY="http://localhost:8080"
方法1ではプロキシが平文の HTTP リクエストを受け取るので、中身を確認・変更(認証情報の注入も含む)してから本物の API に転送できます。方法2では HTTPS は CONNECT トンネルで暗号化されたまま通るため、TLS を終端しない限りプロキシは中身を見ることも変えることもできません。プロキシは自作のほか、credential_injector フィルタを持つ Envoy、HTTPS を終端して検査できる mitmproxy、アクセス制御リストを持つ Squid、認証情報の注入とレート制限を持つ LLM ゲートウェイの LiteLLM が挙げられています(ゲートウェイの接続は「Claude Code を LLM ゲートウェイに接続する」参照)。
Claude API 以外(git リポジトリ、データベース、社内 API)の認証情報には2つの方法があります。
- カスタムツール: MCP サーバーやカスタムツールを用意し、実際の認証付きリクエストは境界の外で行います。たとえば git 用の MCP サーバーがエージェントからコマンドを受け、ホスト側の git プロキシが認証を付けてリモートへつなぎます。TLS を傍受せずに済み、エージェントにはツールのインターフェースしか見えません(「Agent SDK のカスタムツール」参照)。
- 通信の転送: GitHub や npm レジストリのような HTTPS 通信に認証情報を足すには、TLS を終端するプロキシをコンテナの外で動かし、そのプロキシの CA 証明書をエージェント側の信頼ストアに入れ、
HTTP_PROXY/HTTPS_PROXYで通信を向けます。カスタムツールを書かずに済む代わりに、証明書の管理が増えます。
なお、すべてのプログラムが HTTP_PROXY / HTTPS_PROXY に従うわけではありません。curl・pip・npm・git などは従いますが、Node.js の fetch() は既定で無視します(Node 24 以降は NODE_USE_ENV_PROXY=1 で有効化できます)。従わないツールまで拾うには、proxychains でネットワーク呼び出しを横取りするか、iptables で外向き通信を透過プロキシへリダイレクトします。透過プロキシはネットワーク層で通信を受け止めるので、クライアント側でプロキシを設定する必要がありません。
ファイルシステムの設定
コードを読むだけで変更は不要なら、ディレクトリを読み取り専用でマウントします。
docker run -v /path/to/code:/workspace:ro agent-image
ただし読み取り専用でも、認証情報が読めてしまえば漏れます。マウント前に除外または無害化しておくべきファイルとして、公式は次を挙げています。
| ファイル | リスク |
|---|---|
.env、.env.local | API キー、データベースのパスワード、シークレット |
~/.git-credentials | 平文の Git パスワード・トークン |
~/.aws/credentials | AWS のアクセスキー |
~/.config/gcloud/application_default_credentials.json | Google Cloud の ADC トークン |
~/.azure/ | Azure CLI の認証情報 |
~/.docker/config.json | Docker レジストリの認証トークン |
~/.kube/config | Kubernetes クラスタの認証情報 |
.npmrc、.pypirc | パッケージレジストリのトークン |
*-service-account.json | GCP のサービスアカウントキー |
*.pem、*.key | 秘密鍵 |
必要なソースファイルだけをコピーするか、.dockerignore 風のフィルタで絞るのが勧められています。
書き込みが必要な場合は、変更を残すかどうかで選びます。使い捨ての作業場所なら、メモリ上にだけ存在しコンテナ停止で消える tmpfs を使います。
docker run \
--read-only \
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--tmpfs /workspace:rw,noexec,size=500m \
agent-image
変更を確認してから反映したいなら、オーバーレイファイルシステムを使えば元のファイルを変えずに書き込ませ、別レイヤーに溜まった変更を確認して適用または破棄できます。成果物を完全に残したいなら専用のボリュームをマウントし、重要なディレクトリとは分けておきます。コンテナの運用構成そのものは「Agent SDK のホスティング」で扱っています。
本ページは Securely deploying AI agents を中心に、anthropics/sandbox-runtime の README の記述を踏まえた非公式の日本語解説です(確認日 2026-10-30)。最新の仕様は公式ドキュメントを確認してください。