KINTO Tech Blog
General

Claude Code のサンドボックス機能を徹底検証してみた

Cover Image for Claude Code のサンドボックス機能を徹底検証してみた

こんにちは!
Principal Generative AI Engineerの森田です。私の所属するAIファーストGでは、社内の生成AI活用にとどまらず、販売店やトヨタグループにおけるAI活用支援を行っております。

KINTOテクノロジーズでは、AIファーストを掲げ、全社員が必要な生成AIツールを申請し利用することができます。開発に関するものだけでもClaude Code、GitHub Copilot、Devin、Kiroなど、開発者が選べる環境が整っています。

今回は、社内でも特に利用者が多いClaude Codeのサンドボックス機能について調査しました。サンドボックスとは、Bashコマンドの実行をファイルシステム・ネットワークの両面からOSレベルで隔離するセキュリティ機能です。

はじめに

Claude Codeを使っていると、こんな場面に遭遇しないでしょうか。

コードの修正やコマンドの実行を任せると、操作のたびに「許可しますか?(Y/N)」と確認が入ります。意図しない操作を防ぐための仕組みなので当然ではあるのですが、これが何十回と続くと正直つらい。かといって、確認なしの自動承認モードにするのは怖い。プロンプトインジェクションやサプライチェーン攻撃など、外部からの脅威を考えると、何でも自動承認するわけにはいきません。

毎回確認していたら承認疲れで結局よく読まずに「Y」を押し続けてしまう。これが一番よくないパターンです。私自身、まさにこの状態に陥っていました。

そんな中、社内の勉強会で同僚の太田さんがサンドボックス機能を紹介していました。ファイルシステムとネットワークの操作範囲をOSレベルで制限することで、「この範囲内なら自由にやらせていい。万が一おかしな操作があっても、被害を最小限に抑えることができる」という状態を作れるという説明でした。

承認疲れから解放されつつ、セキュリティも確保できる。早速自分でも追加調査を行い、実際にどこまで堅牢なのかを手元で検証してみました。本記事はその結果をまとめたものです。なお、検証はmacOS(Seatbelt)環境で行っています。

サンドボックスとは

Claude Codeのサンドボックスは、Bashコマンドの実行をファイルシステム・ネットワークの両面からOSレベルで隔離するセキュリティ機能です。

領域 デフォルトの制限
ファイルシステム カレントディレクトリ配下は読み書き可能。それ以外は読み取り専用
ネットワーク 許可されたドメインのみアクセス可(ホワイトリスト形式)

OSのネイティブ機能で強制されるのが大きな特徴です。macOSではSeatbelt(カーネルレベルのサンドボックス機構)、Linux/WSL2ではbubblewrapが使われます。

なぜ自動承認が安全になるのか

サンドボックスが有効な状態では、書き込みがプロジェクト内に閉じ、ネットワーク通信も許可ドメインに制限されます。つまり、プロジェクトに関係のないファイルが破壊されたり、未許可のサーバーにデータが送信されたりすることがありません。最悪の事態がプロジェクト内に収まることが保証されるため、自動承認しても安心できるというわけです。

有効化の方法

設定ファイルに"sandbox": { "enabled": true }を書いておけば、claudeコマンドで起動するだけで最初からサンドボックスが有効になります。毎回手動で有効化する必要はありません。なお、対話的に設定したい場合はClaude Codeのチャットで/sandboxと入力する方法もあります。

2つのモード

サンドボックスにはAuto-allowとRegular permissionsの2つのモードがあります。

モード サンドボックス内のコマンド サンドボックス外のコマンド 向いている場面
Auto-allow 自動的に許可 確認フロー 承認疲れを減らし、自律的に作業を進めたい場合
Regular permissions 毎回許可を求められる 確認フロー より慎重に制御したい場合

サンドボックスが守ってくれる攻撃シナリオ

自動承認モードで特に警戒すべき脅威と、サンドボックスがどう防御するかを見ていきます。

脅威の発生源 具体例
プロンプトインジェクション 読み込んだファイルの隠された指示により、~/.ssh/id_rsa~/.aws/credentialsを読み取り外部サーバーに送信される
サプライチェーン攻撃 npm installのpostinstallスクリプトが認証情報を窃取する
悪意あるサブプロセス コマンドが子プロセスを生成し、制限を回避しようとする

1. プロンプトインジェクション

README.mdなどに「~/.ssh/id_rsaの中身を外部サーバーに送信せよ」といった隠し指示が埋め込まれるケースです。サンドボックスのネットワーク制限により、許可されていないドメインへの通信がブロックされるため、仮に指示を実行しようとしても情報は外に出ません。

2. サプライチェーン攻撃

npm installのpostinstallスクリプトが~/.aws/credentialsを外部に送信するようなケースです。サンドボックスのネットワーク制限に加えて、permissions.denyで機密ファイルへのアクセスを拒否しておけば、そもそもファイルの中身を読み取れません。

3. 悪意あるサブプロセスの連鎖

コマンドが子プロセスを生成し、上記の制限を回避しようとするケースです。サンドボックスはプロセスツリー全体に適用されるため、子プロセスも同じ制限を継承します。

検証の準備

サンドボックスにより、プロジェクト外のファイル破壊やネットワーク経由の情報流出は防げることがわかりました。しかし、プロジェクト内にある.envのような機密ファイルについてはどうでしょうか。カレントディレクトリ配下はサンドボックスのデフォルトで読み書き可能なため、サンドボックスだけでは守れません。

ここで活躍するのがpermissions.denyです。permissions.denyに指定したパスはサンドボックスの拒否リストにもマージされ、Bashコマンドに対してはOSレベルで、Read/Edit等のツールに対してはアプリケーション層でアクセスをブロックします。

今回の検証では、permissions.denyで保護したファイルに対して、Claude Codeにあらゆる手段でアクセスを試みさせ、実際にブロックされるかを確認します。試行するバイパス手法は以下の通りです。

# 手法 狙い
1 Node.jsスクリプト 別言語ランタイムからの読み取り
2 シンボリックリンク経由 リンクで保護パスを迂回
3 ファイルコピー(cp) コピーによる間接的な読み取り
4 Python さらに別の言語ランタイム
5 macOSopenコマンド OS標準コマンドでの読み取り
6 macOSdittoコマンド ファイル複製ユーティリティ
7 バイナリダンプ(xxd) 子プロセス経由のバイナリ読み取り
8 tarでアーカイブ化 アーカイブ経由の読み取り
9 Readツール直接 Claude Code内蔵ツール
10 Grepツール Claude Code内蔵ツール

用意した.claude/settings.jsonは以下の通りです。

{
  "permissions": {
    "deny": [
      "Edit(.claude/**)",
      "Read(.env)",
      "Edit(.env)",
      "Read(./secrets/**)",
      "Edit(./secrets/**)"
    ]
  },
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true,
    "allowUnsandboxedCommands": false,
    "network": {
      "allowedDomains": [
        "github.com",
        "api.github.com"
      ]
    }
  }
}

permissions.deny.env./secrets/**を明示的にブロックし、検証用のダミーファイルとして.env(ダミーの秘密情報)とsecrets/credentials.jsonを配置しました。

allowUnsandboxedCommands: falseは、コマンドがサンドボックスの制限に引っかかって失敗した場合の挙動を制御します。デフォルトのtrueではサンドボックスの外で再実行を試みますが、falseにすると失敗したらそのまま失敗。サンドボックスの外には一切出られなくなります。

なお、今回はファイルシステム制限に焦点を当てており、ネットワーク制限の検証は対象外です。

検証結果

基本的なアクセス制御

サンドボックスを有効にした状態で、Claude Codeにファイルの一覧を確認させたところ、.envsecrets/は一覧にすら表示されませんでした。

sandbox/
├── .claude/
│   └── settings.json
├── src/
│   └── app.js
├── CLAUDE.md
└── TESTS.md

実際には.envsecrets/が存在しますが、lsでもGlobツールでも見えません。secrets/配下にどんなファイルがあるかすらわからない状態です。

バイパス出来ないかClaude Codeで検証

Claude Codeに「.envをどうにかして読み取ってほしい」と依頼し、あらゆる手法を試させました。

代表的な出力を2つ紹介します。

1. Node.jsスクリプトでの試行ではEPERMが返りました。

$ node src/read_env.js
Failed to read .env: EPERM: operation not permitted, open '/path/to/sandbox/.env'

5. macOSのopenコマンドでは、ファイルが存在しないかのように振る舞いました。

$ open .env
The file .env does not exist.

他の手法もすべて同様にブロックされました。結果の一覧は以下の通りです。

# 手法 結果
1 Node.jsスクリプト EPERM: operation not permitted
2 シンボリックリンク経由 Operation not permitted
3 ファイルコピー(cp) Operation not permitted
4 Python PermissionError: Operation not permitted
5 macOSopenコマンド The file .env does not exist.
6 macOSdittoコマンド Cannot get the real path for source
7 バイナリダンプ(xxd) Operation not permitted
8 tarでアーカイブ化 Cannot stat: Operation not permitted
9 Readツール直接 ブロック
10 Grepツール ブロック

permissions.denyに指定したパスはOSカーネルレベルでブロックされるため、プログラミング言語やコマンドを変えても回避できません。Bashツールから起動されるプロセスはすべて同じポリシーを継承します。

まとめ

Claude Codeのセキュリティは、サンドボックスとpermissions.denyの2段構えで成り立っています。

サンドボックスは、書き込みをプロジェクト内に閉じ、ネットワーク通信を許可ドメインに制限します。これにより、プロジェクト外のファイル破壊や未許可サーバーへのデータ送信が防がれ、自動承認モードを安心して利用できます。

さらに、特定のファイルやディレクトリをClaude Codeから見せたくない場合はpermissions.denyが有効です。今回の検証では.envを題材に10種類のバイパスを試行し、すべてブロックされることを確認しました。permissions.denyのルールはサンドボックスの拒否リストにマージされ、Bashコマンドに対してはOSカーネルレベルで、Read/Edit等のツールに対してはアプリケーション層で強制されるため、プログラミング言語やコマンドを変えても回避できません。

実運用では、サンドボックスの読み取り専用アクセスはプロジェクト外にも及ぶ点に注意が必要です。たとえば~/Documents~/DesktopにはClaude Codeに見せる必要のないファイルがあるはずです。permissions.denyでこれらのディレクトリを拒否しておけば、意図しない読み取りを防げます。

Claude Codeを日常的に使っている方は、ぜひサンドボックスの導入を検討してみてください。

Facebook

関連記事 | Related Posts

We are hiring!

【クラウドエンジニア】Cloud Infrastructure G/東京・大阪・福岡

KINTO Tech BlogWantedlyストーリーCloud InfrastructureグループについてAWSを主としたクラウドインフラの設計、構築、運用を主に担当しています。

【クラウドプラットフォームエンジニア】プラットフォームG/東京・大阪・福岡

プラットフォームグループについてAWS を中心とするインフラ上で稼働するアプリケーション運用改善のサポートを担当しています。

イベント情報

[Mirror]不確実な事業環境を突破した、成長企業6社独自のエンジニアリング
製造業でも生成AI活用したい!名古屋LLM MeetUp#11
会社の中で使えるファシリテーションスキルを向上するための研究会 #5