Claude Code で npm install や terraform / kubectl を勝手に走らせるのが怖い人向け
npm install や terraform、kubectl のようにファイルやネットを書き換えるコマンドを Claude Code に任せたい初日や、git clone してきたばかりの初見プロジェクトを触らせる場面で、毎回の許可ダイアログをやめつつホームや SSH 鍵を守りたい時に <code>/sandbox</code> を叩いてモードを選ぶ。macOS は標準で動き、Linux/WSL2 は事前に <code>bubblewrap</code> と <code>socat</code> を入れる。WSL1 とネイティブ Windows は現状非対応。
Claude Codeに npm install や terraform apply を任せるとき、毎回毎回「これ走らせていいですか」のYes/Noダイアログが出ると、しまいには中身を見ずにエンターを連打する自分に気づきます。だからといって全許可にすると、悪意あるパッケージや書き換えられた手順を踏んだとき、家のドット設定ごと吹き飛ばされかねない。私もこの「許可疲れ」と「全許可の怖さ」の板挟みで2回ほど作業を止めました。
/sandbox は、その挟まれた状態を1コマンドで仕切り直すためのスラッシュコマンドです。OSの仕組みを使って「ここから先のファイルは触らせない」「このアドレス以外のネットは見せない」と境界線を引いた箱の中でだけ、Claude CodeのBashを動かす。境界の中なら自由に走ってもらって、外に手を出した瞬間にだけ私が呼び出される、という設計に切り替わります。
噛み砕くと
イメージは「マンションの一室を仕事用に借りた」状態に近いです。部屋の中なら家具の配置を変えても落書きをしても構わない。でも玄関の外に出ようとした瞬間に管理人が止めにくる。Claude Codeにとっての「部屋」が今いるプロジェクトフォルダ、「玄関の外」がホームディレクトリや別ドライブ、「玄関の鍵」をあらかじめ管理人(私)が許可した相手にだけ渡す。それが /sandbox の世界観です。
/sandbox を叩くと、その境界線をどのくらいきっちり敷くかをメニューで選ばされます。「中で動く分は自動でOKにする」モードか、「箱の中であっても1回ずつ私に聞く」モードか。境界線の硬さは同じで、違うのは「中で起きることの自動承認」だけ、というのが地味だけど大事な勘所です。
大事な前提:使えるのは macOS と Linux と WSL2 だけ
これは公式が明確に線を引いている部分なので最初に潰しておきます。/sandbox は OS が持っている分離機能を借りる作りなので、対応OSが限られます。
- macOS: 標準搭載の
Seatbeltをそのまま使う。追加で何かを入れる必要なし - Linux:
bubblewrapとsocatを別途インストールが必要。Ubuntu/Debian なら apt、Fedora なら dnf のパッケージで入る。具体的なコマンドは公式 sandboxing docs の Prerequisites 節にあります - WSL2: 中身は Linux と同じ。
bubblewrap・socatを入れる - WSL1: 非対応。公式いわく「
bubblewrapが必要とするカーネル機能が WSL2 にしかない」 - ネイティブ Windows: 現状なし。公式は将来予定とだけ書いている
もうひとつ Ubuntu 24.04 以降の落とし穴があります。bubblewrap を入れただけでは AppArmor が bwrap の名前空間作成をブロックします。AppArmor 設定ディレクトリの中に bwrap 用の小さい profile を1枚足して、AppArmor サービスを読み直させる必要がある。「動かない」と感じる人の大半はこれが原因です。
「料理ブログを Hugo で立ち上げる」を例に、実際の手順を見る
題材は「料理ブログを Hugo というサイトジェネレータで作る」想定です。npm install や hugo server を Claude Code に任せたいけど、ホームフォルダの設定ファイルや SSH 鍵まで触られるのはイヤ、というよくあるシーン。/sandbox をどう叩いて、どっちのモードを使い分けるかを順に見ます。
ステップ1: 対応OSと依存を確認する
macOS なら追加作業なし。Ubuntu 24.04 以降を使っている場合は最低でも次の 3 つを通す必要がある。
- Ubuntu/Debian なら管理者権限で
apt-get install bubblewrap socatを実行してパッケージを入れる。Fedora の場合はdnf install bubblewrap socat - AppArmor の profile を 1 ファイル足す:
bwrapにuserns(名前空間作成)を許可する短い profile を AppArmor 設定ディレクトリの中に置く。具体的な書式は 公式 sandboxing docs の Prerequisites 節にコピペできる雛形があるので、そこから取ってきて貼る - AppArmor サービスを管理者権限で読み直させる。reload コマンドの正確な形は同じ公式 docs に1行で載っている
この AppArmor 設定が抜けていると、次のステップでメニューがエラーメッセージを返してきます。動かない時はだいたいこの 3 つのどれかが抜けていると思っていい。
ステップ2: 料理ブログのプロジェクトで Claude Code を起動する
プロジェクト直下に cd してから claude を起動。「私はこの cooking-blog/ フォルダの中だけで作業させたい」という前提を、ここで物理的に成立させておきます。
$ cd ~/projects/cooking-blog
$ claude
ステップ3: /sandbox を叩いてモードを選ぶ
Claude Code が立ち上がったら、入力欄に /sandbox と打って Enter。すると2択メニューが出ます。
> /sandbox
Choose a sandbox mode:
1. Auto-allow mode - Run sandboxed commands automatically
2. Regular permissions mode - Sandbox + per-command approval
料理ブログを立ち上げる初日なら、私は Auto-allow を選びます。npm install も hugo new site も hugo server も全部「フォルダの中で完結する作業」なので、いちいち聞かれずに走ってくれた方がリズムが出る。逆に本番デプロイ用の鍵を扱うフォルダなら Regular permissions 側にする、という使い分けになります。
ステップ4: npm install が砂場の中で走るのを確認する
Hugo は Go 製ですがテーマで npm を要求するものが多いので、テーマインストール用の npm install を Claude に頼みます。
> テーマフォルダで npm install を実行して
Bash(npm install) [sandboxed]
added 312 packages in 14s
普段なら「npm install 実行していい?」のダイアログが出るところが、今回は [sandboxed] マークがついて勝手に走り、ホームの ~/.bashrc や ~/.ssh/ には指1本触れない状態で終わります。これが「Auto-allow なのに安全」の正体です。書ける範囲が ~/projects/cooking-blog/ 以下に物理的に絞られているから、自動承認してもダメージ範囲が決まっている。
ステップ5: ホームの ~/.kube に書きたい時だけ穴を開ける
あとでサイトを Kubernetes にデプロイする予定があり、kubectl が ~/.kube/config を書き換える必要が出てきたとします。素のままだと砂場の外なので失敗する。.claude/settings.json に追記して、その1か所だけ書き込みを許可します。
{
"sandbox": {
"enabled": true,
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"]
}
}
}
ポイントは 「広く開けず、必要なフォルダだけ開ける」 こと。「ホームディレクトリ全体を許可」みたいな書き方をすると、~/.bashrc や ~/.zshrc も書ける範囲に入ってしまい、攻撃された時にターミナル起動時の自動読み込みファイルを書き換えて次回ログイン時に任意コードが走る、という古典的な攻撃が成立してしまいます。
ステップ6: ネットの行き先を registry.npmjs.org だけに絞る
ファイルだけじゃなくネットの行き先もこの段階で絞っておきます。npm install が触りに行く先は基本的に registry.npmjs.org なので、そこだけ通せばいい。
{
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["registry.npmjs.org"]
},
"filesystem": {
"allowWrite": ["~/.kube", "/tmp/build"]
}
}
}
ここで初心者がやりがちな勘違いがあります。「github.com だけ通せばだいたい大丈夫」と書きたくなる。これがやばい。Claude Code 公式は明確に警告していて、github.com のような広い行き先は domain fronting という手口で外に抜けられる可能性がある。書く時はサブドメインまで細かく指定するのが正解です。
つまり /sandbox は何をしてくれるのか
- やってくれる: 今のプロジェクトフォルダの中だけで
Bashを動かす境界線を引く。npm installやterraform planを自動承認しても、ホームの設定ファイルや SSH 鍵には触れない - やってくれる: ネットの行き先を
allowedDomainsで絞る。専用の中継サーバー経由で外行きの通信が監視され、リスト外は弾かれる - やってくれる: Auto-allow モードでも、
rm /やrm -rf ~のようにシステム上の大事な場所(/直下やホームディレクトリ~全体など)を狙うコマンドには必ず確認が出る。「自動承認している = 何でも走る」ではなく、危険コマンドへの安全装置は Auto-allow でも効いている - やってくれない:
Read/Edit/Writeといった Claude Code 組み込みのファイルツールの監督。これらは砂場の外にいて、permissionsの許可設定で別管理になる - 意味が薄い場面: WSL1 環境、ネイティブ Windows 環境、Docker 中で動かしている開発環境(後者は
enableWeakerNestedSandboxで動くが強度がガクッと落ちる)
Auto-allow と Regular permissions、何が違うのか
ここで2モードの違いを表にしておきます。境界線の硬さは同じで、違うのは「中の自動承認」だけ、というのが見えれば十分。
| モード | 箱の中の Bash | ファイル制限 | ネット制限 | deny ルール | rm / / rm ~ |
向いてる人 |
|---|---|---|---|---|---|---|
| Auto-allow | 自動で走る | 同じ | 同じ | 常に効く | 必ず確認が出る | 初日のセットアップ・OSS取得直後 |
| Regular permissions | 1個ずつ確認 | 同じ | 同じ | 常に効く | 必ず確認が出る | 本番用フォルダ・秘匿情報を扱う場面 |
「Auto-allow にしたら全自動で何でも走る」と聞こえがちですが、箱の外に出る通信は普通の許可フローに戻されるし、明示的な deny ルールは何があっても効く。rm と rmdir がシステム重要フォルダを狙っている場合も普通に止まります。安全装置は意外と多重に効いている。
使いどころ3シナリオ(具体題材で再現)
シナリオ1: 料理ブログを Hugo で立ち上げる初日
テーマ選定、hugo new site、npm install でテーマの依存を入れる、hugo server で確認、の流れを止めずに回したい。プロジェクトフォルダ ~/projects/cooking-blog/ の中で完結する作業なので、Auto-allow にして、allowedDomains に registry.npmjs.org と themes.gohugo.io を入れておく。これだけで「npm install していい?」のダイアログが消え、3〜4時間の試行錯誤が止まらない。私はこの組み合わせをデフォルトの初日設定にしています。
シナリオ2: OSS を git clone してきた直後
「awesome-go-cli みたいな初見のプロジェクト一式を git clone で自分のパソコンに取り寄せて、まず Claude Code に構造を読ませる」場面。中の package.json に怪しい postinstall が仕込まれているかもしれない、というのは現実にある話。/sandbox を Auto-allow で有効化、allowedDomains を registry.npmjs.org 限定にしておくと、もし postinstall が攻撃者のサーバーに通信しようとしても外で弾かれます。プロジェクトフォルダの外にも書けないので、最悪でも被害はそのフォルダの中で止まる。
シナリオ3: terraform plan を試したい時
インフラ系のコマンドは「クラウドの認証情報を ~/.aws/ や ~/.kube/ から読む」「ローカルの .terraform/ に状態ファイルを書く」が混在します。Regular permissions モードに切り替えて、sandbox.filesystem.allowWrite に ~/.kube と ./.terraform を足し、AWS の SDK が叩くドメインだけ allowedDomains に入れる。Auto-allow よりは打鍵回数が増えるけど、本番リソースを動かすコマンドが混じる場合は私は Regular permissions 側に倒します。これ正直、心の平穏のためです。
初心者が踏みやすい落とし穴
- WSL1 で
/sandboxを期待する。公式が「bubblewrapが必要とするカーネル機能が WSL2 にしかない」と明言しているので動きません。WSL2 にアップグレードするか、/sandboxを諦めるかの2択 - Linux で
bubblewrapとsocatを入れ忘れる。Ubuntu/Debian なら apt の、Fedora なら dnf のパッケージマネージャから入る。メニューが「インストール手順を表示」と言ってくる場合はこれが原因 - Ubuntu 24.04+ で AppArmor profile を書き忘れる。
bwrapに名前空間作成を許可する小さい profile(本文ステップ1)を AppArmor 設定ディレクトリに置き、AppArmor サービスを再読み込みさせる。これを抜くと「動かない」しか分からないので踏みやすい allowedDomainsにgithub.comのような広いドメインを書く。中継サーバーがhttps://の中身まで見ない仕様なので、広い許可はdomain frontingで抜けられる余地がある。書く時はサブドメインまで細かくsandbox.filesystem.allowWriteにホーム配下を雑に書く。~/.bashrcや~/.zshrcが書ける範囲に入ると、攻撃者がそれを書き換えて次回ログイン時に任意コードを走らせるルートが開く。必要な1か所だけ開ける- 「
/sandboxを有効にしたからpermissionsは緩めていい」と誤解する。両者は二層構造で、permissionsは全ツールの最初のゲート、/sandboxはBash系だけの OS レベル壁。両方有効にして初めて意味が出る - Auto-allow を「全部勝手に走る」と思い込む。明示的な
denyルール、rm/rmdirが/やホームを狙う場合、外向き通信が許可外、これらは全部止まる。多重の安全装置がある前提で設計されている Read/Edit/Writeのファイル系ツールが砂場で守られると思い込む。これらは砂場を通らずpermissionsで直接管理される。denyRead/denyWriteルールは砂場とRead/Edit両方にマージされる、というのが正しい理解watchmanやdockerをそのまま走らせて失敗する。砂場と相性が悪いツールがあって、Jest ならjest --no-watchman、dockerならexcludedCommandsにdocker *を入れて砂場の外で走らせる、という回避策が公式の Tip に書いてある
書き方
/sandbox
やってみるとこうなる
入力
/sandbox
出力例
Choose a sandbox mode:
1. Auto-allow mode - Run sandboxed commands automatically
2. Regular permissions mode - Sandbox + per-command approval
# モード選択後、以降の Bash は [sandboxed] マークつきで走る
Bash(npm install) [sandboxed]
added 312 packages in 14s
このページに出てきた言葉
- サンドボックス
- プログラムを動かす範囲を「砂場」のように囲って、外のファイルやネットに触れないようにする仕組み
- Seatbelt
- macOS が標準搭載している、アプリの動きを箱に閉じ込めるための機能。<code>/sandbox</code> が macOS で使う土台
- bubblewrap
- Linux 上で「このプログラムには見せるフォルダだけ見せる」を実現するツール。<code>/sandbox</code> が Linux/WSL2 で使う土台。コマンド名は <code>bwrap</code>
- socat
- 通信の入口と出口をつなぎ直す道具。Claude Code が砂場の中と外をやり取りするときの配管役
- AppArmor
- Ubuntu 系 Linux の標準ルール集。Ubuntu 24.04 以降は <code>bwrap</code> を unconfined にする profile を別途書く必要がある
- WSL2
- Windows の中で Linux を動かす公式の仕組みの第2世代。<code>/sandbox</code> は WSL2 では使えるが WSL1 では使えない
- allowedDomains
- <code>/sandbox</code> 設定の中で「ここへの通信だけは通す」と指定するドメインの一覧。<code>github.com</code> のような広い指定は <code>domain fronting</code> で抜けられるリスクがある
- domain fronting
- 通信の最初の宛先と実際の中身の宛先をズラして、許可されたドメインのフリをして許可外の場所と通信する手口
- permissions
- Claude Code が全ツールに対して「許す/聞く/禁止」を決める仕組み。<code>/sandbox</code> より広く、最初のゲートになる層
- dangerouslyDisableSandbox
- 個別コマンドだけ砂場の外で走らせる逃げ道。完全に塞ぐ場合は <code>allowUnsandboxedCommands: false</code> で無効化する
- excludedCommands
- <code>/sandbox</code> 設定の中で「このコマンドだけは砂場の外で走らせる」と指定するリスト。<code>docker *</code> や WSL2 上の <code>cmd.exe</code> をここに入れる