📦

Claude CodeのSandboxing機能を試してみる:ネットワーク分離

に公開

前回のエントリーでは、Claude CodeのSandboxing機能のうち、「ファイルシステムレベルの分離」について試した結果をまとめてみました。

https://zenn.dev/tomioka/articles/0496a427f8bcd0

このエントリーでは、そちらでは試していなかった「ネットワークレベルの分離」について試してみました。なお、このエントリー時点での私の実行環境はmacOS Tahoe 26.0.1、Claude Codeは2.0.31です。

Claude CodeのSandboxing機能を試す

Sandboxing機能の公式ドキュメントは以下です。

https://docs.claude.com/en/docs/claude-code/sandboxing

Sandboxing機能を有効にすると、ドメインレベルで承認済みの範囲でしかアクセスが認められず、新しいドメインへのアクセスは都度ユーザーの許可を求めるようになるということです。これにより、許可されていないウェブサイトから問題のあるモジュール等をダウンロードしてしまったり、信頼できないウェブサイトに対してアクセスするという問題を抑止してくれるということです。

また、Claude Codeの標準のプロキシーではなく、カスタムプロキシーを介してより詳細なルールを適用できるようです。セットアップに少し手間がかかりそうですが、こちらも試していきたいと思います。

ネットワーク分離を試す

Sandboxingのネットワーク分離機能を試すために、GitHubのリポジトリをクローンしてみます。リポジトリの中身は重要ではないのでREADME.mdだけの空のリポジトリを使います。まずはSandboxing機能を有効にする前に試してみます。当然のように成功します。

> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ GitHubリポジトリをクローンします。

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Cloning into 'claude_code_sandboxing'...

⏺ リポジトリのクローンが完了しました。claude_code_sandboxingディレクトリに展開されています。

一度Claude Codeを抜けて、ローカルにクローンしたリポジトリを削除した後に、今度はSandboxing機能を有効にして同じことを実行します。なお、Sandboxing機能は前回のエントリーと同様に「Accept-edits mode」の方で設定しています。今回はSandbox環境外のgithub.comへのアクセスということで許可が求められました。今後も再びこのドメインへのアクセス時に確認を求めて欲しいなら選択肢1の「Yes」を選びます。今回は、github.comを信頼できるドメインとする選択肢2の「Yes, and don't ask again for github.com」を選びます。リポジトリのクローンが成功しました。

> /sandbox 
  ⎿  ✓ Sandbox enabled with auto-allow for bash commands when in accept-edits mode

> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ GitリポジトリをCloneします。

  Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Cloning into 'claude_code_sandboxing'...
     (8s)
     ctrl+b to run in background

· Determining… (esc to interrupt)
  ⎿  Tip: Run claude --continue or claude --resume to resume a conversation

────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
 Network request outside of sandbox

   Host: github.com

   Do you want to allow this connection?
     1. Yes
   ❯ 2. Yes, and don't ask again for github.com
     3. No, and tell Claude what to do differently (esc)

⏺ Bash(ls -la claude_code_sandboxing)
  ⎿  total 16                                          
     drwxr-xr-x   5 john  staff   160 114 08:17 .
     drwxr-xr-x   4 john  staff   128 114 08:17 ..
     … +3 lines (ctrl+o to expand)

⏺ Successfully cloned the repository to claude_code_sandboxing/. The repository contains:
  - .git/ (Git repository data)
  - .gitignore
  - README.md
> 

この時にどのように設定がされているかと言うと、カレントディレクトリから見て.claude/settings.local.jsonにあるローカルプロジェクトレベルの設定ファイルの中のパーミッションパラメータで、Webアクセスドメインのリストを以下のようにallow(許可)対象として持っています。この設定であれば、Sandboxing機能が有効であっても、次回以降のGitHubリポジトリのクローンのネットワークアクセスで確認が求められることはありません。

% cat ./.claude/settings.local.json 
{
  "sandbox": {
    "autoAllowBashIfSandboxed": true,
    "enabled": true
  },
  "permissions": {
    "allow": [
      "WebFetch(domain:github.com)"
    ]
  }
}

ではこのallow(許可)をdeny(拒否)に変えるとどうなるかを試してみます。ローカルにクローンしたリポジトリを削除した後に、settings.local.jsonの設定をallowからdenyに変更し、先ほどと同じことを試してみます。今回は拒否されました。また、Sandboxing機能の解除を求められましたので、それは拒否しています。その結果、リポジトリのクローンは失敗しました。

% cat ./.claude/settings.local.json 
{
  "sandbox": {
    "autoAllowBashIfSandboxed": true,
    "enabled": true
  },
  "permissions": {
    "deny": [
      "WebFetch(domain:github.com)"
    ]
  }
}
% claude
> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ I'll clone the repository for you.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Error: Exit code 128
     Cloning into 'claude_code_sandboxing'...
     fatal: unable to access 'https://github.com/sn6t/claude_code_sandboxing/': CONNECT tunnel failed, response 403

⏺ The git clone failed due to sandbox network restrictions. Let me retry with sandbox disabled to allow the network
  connection to GitHub.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Interrupted · What should Claude do instead?

Sandboxing機能を解除すると、上記のdeny(拒否)設定が.claude/settings.local.jsonに入っていてもネットワーク通信は許可されます。そのため、webFetchのパーミッション設定はSandboxing機能が有効な場合のみに意味があるということになります。

> /sandbox 
  ⎿  ○ Sandbox disabled

> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ サンドボックスが無効になったので、リポジトリをクローンします。

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Cloning into 'claude_code_sandboxing'...

⏺ リポジトリのクローンが完了しました。内容を確認します。

⏺ Bash(ls -la claude_code_sandboxing)
  ⎿  total 16                                          
     drwxr-xr-x   5 john  staff   160 11月  4 08:41 .
     drwxr-xr-x   4 john  staff   128 11月  4 08:41 ..
     … +3 lines (ctrl+o to expand)

⏺ リポジトリのクローンに成功しました。claude_code_sandboxing ディレクトリが作成されました。

  リポジトリの内容:
  - .gitignore
  - README.md

  README.mdの内容を確認しますか?
> 

ここまでやってきた.claude/settings.local.jsonはローカルプロジェクトレベルの設定ファイルだったのですが、このファイルがない状態で、共有プロジェクトレベルの設定ファイル(.claude/settings.json)で拒否した場合はどうなるのでしょうか。以下のように試してみましたが、この場合は./claude/settings.jsonの拒否設定が有効なようです。ドメインレベルのアクセス許可確認ではなく、Sandboxing機能の無効化の許可が求められました。

% cat settings.local.json 
{
  "sandbox": {
    "enabled": true,
    "autoAllowBashIfSandboxed": true
  }
}
% cat ./.claude/settings.json                       
{
  "sandbox": {
    "autoAllowBashIfSandboxed": true,
    "enabled": true
  },
  "permissions": {
    "deny": [
      "WebFetch(domain:github.com)"
    ]
  }
}
% claude
> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ I'll clone the repository for you.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Error: Exit code 128
     Cloning into 'claude_code_sandboxing'...
     fatal: unable to access 'https://github.com/sn6t/claude_code_sandboxing/': CONNECT tunnel failed, response 403

⏺ The sandbox is blocking network access to GitHub. Let me retry with sandbox disabled to access the repository. Use
   /sandbox to manage restrictions.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Interrupted · What should Claude do instead?
> 

カスタムプロキシーを試す

続いてカスタムプロキシーを試します。ローカルマシン(macOS Tahoe 26.0.1)にSquidを立てて、接続を確認します。HomebrewでSquidをインストールして、サービスを立ち上げて、通信が出来ていることと、Squidのアクセスログが出力されていることを確認します。別のシェルのウインドウを立ち上げて作業はそちらで行い、元のシェルではアクセスログをtail -fしておきます(アクセスログが追加出力されたらリアルタイムに表示するだけなので、この手順は必須ではないです)。

% brew install squid
% brew info squid
==> squid: stable 7.3 (bottled), HEAD
% brew services start squid
==> Successfully started `squid` (label: homebrew.mxcl.squid)
% curl https://www.google.com -x http://localhost:3128
<!doctype html>(中略)</html>
% cat /opt/homebrew/var/logs/access.log 
1762226934.497    547 ::1 TCP_TUNNEL/200 24089 CONNECT www.google.com:443 - HIER_DIRECT/142.250.196.100 -
% tail -f /opt/homebrew/var/logs/access.log
1762226934.497    547 ::1 TCP_TUNNEL/200 24089 CONNECT www.google.com:443 - HIER_DIRECT/142.250.196.100 -

settings.local.jsonの設定で、今立てたSquidのプロキシーをHTTPプロキシーサーバーとして指定してClaude Codeを起動します。この状態はSandboxing機能は有効ではありません。Sandboxing機能は有効ではないので、問題なくリポジトリのクローンは成功しますし、Squidのプロキシーのアクセスログは出力されません。つまりカスタムプロキシーサーバーは通らないということです。

% cat settings.local.json 
{
  "sandbox": {
    "network": {
      "httpProxyPort": 3128
    }
  }
}
% claude
> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ I'll clone the repository for you.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Cloning into 'claude_code_sandboxing'...

⏺ The repository has been successfully cloned! Let me check what's in it:

⏺ Bash(ls -la claude_code_sandboxing)
  ⎿  total 16                                          
     drwxr-xr-x   5 john  staff   160 11月  4 12:46 .
     drwxr-xr-x   4 john  staff   128 11月  4 12:46 ..
     … +3 lines (ctrl+o to expand)

⏺ The repository has been cloned to /path/to/your/sandbox/claude_code_sandboxing. Let me show you the
  README:

⏺ Read(claude_code_sandboxing/README.md)
  ⎿  Read 1 line

⏺ Successfully cloned the repository! It's now located at /path/to/your/sandbox/claude_code_sandboxing.

  The repository currently contains:
  - .gitignore
  - README.md (with just the title "claude_code_sandboxing")

  The repository appears to be minimal at the moment. Is there something specific you'd like to do with it?

ローカルのリポジトリを削除した後、再びClaude Codeを立ち上げ、Sandboxing機能を有効にした後に同じことを実施します。今回はSandboxing機能が有効であり、かつsettings.local.jsonのwebFetch設定でallowもdenyもしていないにもかかわらず、リポジトリのクローンは成功しました。

> /sandbox 
  ⎿  ✓ Sandbox enabled with auto-allow for bash commands when in accept-edits mode

> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ GitリポジトリをCloneします。

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Cloning into 'claude_code_sandboxing'...

⏺ リポジトリのCloneが完了しました。claude_code_sandboxingディレクトリが作成されています。

また、Squidの方のアクセスログはgithub.comへのアクセスログが出力されていました。つまり、Sandboxing機能を有効にして、httpProxyPort設定が入っていてカスタムプロキシサーバーを通している場合は、webFetchのパーミッション設定は意味がなさそうです。

% tail -2 /opt/homebrew/var/logs/access.log
1762226934.497    547 ::1 TCP_TUNNEL/200 24089 CONNECT www.google.com:443 - HIER_DIRECT/142.250.196.100 -
1762228272.180   1058 ::1 TCP_TUNNEL/200 7428 CONNECT github.com:443 - HIER_DIRECT/20.27.177.113 -

検証のために、settings.local.jsonでdeny設定を明示的にしたらどうなるかを確認します。ローカルマシンにクローンしたリポジトリを削除し、同じことを再試行しましたが成功しました。したがって、Sandboxing機能を有効にして、カスタムプロキシーをhttpProxyPortで設定している場合は、settings.local.jsonのwebFetchパーミッション設定はやはり意味がないということになります。

% cat settings.local.json 
{
  "sandbox": {
    "network": {
      "httpProxyPort": 3128
    },
    "enabled": true,
    "autoAllowBashIfSandboxed": true
  },
  "permissions": {
    "deny": [
      "WebFetch(domain:github.com)"
    ]
  }
}
% claude
> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ I'll clone the repository for you.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Cloning into 'claude_code_sandboxing'...

⏺ The repository has been successfully cloned into the claude_code_sandboxing directory. Let me check what's inside:

⏺ Bash(ls -la claude_code_sandboxing)
  ⎿  total 16                                          
     drwxr-xr-x   5 john  staff   160 114 13:41 .
     drwxr-xr-x   4 john  staff   128 114 13:41 ..
     … +3 lines (ctrl+o to expand)

⏺ The repository has been successfully cloned into /path/to/your/sandbox/claude_code_sandboxing. The
  repository contains:
  - .gitignore
  - README.md

  The clone is complete and ready to use.

では最後に、Squidのプロキシーサーバー側でアクセス制限を設定して挙動を確認します。Squitの設定ファイルであるsquid.confgoogle.comgithub.comへのアクセス制限をacl blocksitesで設定します。そして、google.comへのウェブアクセスは蹴られることを確認しました。

% brew services stop squid
Stopping `squid`... (might take a while)
==> Successfully stopped `squid` (label: homebrew.mxcl.squid)
% vi /opt/homebrew/etc/squid.conf
% cat /opt/homebrew/etc/squid.conf
(中略)
acl Safe_ports port 488		# gss-http
acl Safe_ports port 591		# filemaker
acl Safe_ports port 777		# multiling http

acl blocked_sites .google.com .github.com

#
# Recommended minimum Access Permission configuration:
#
# Deny requests to certain unsafe ports
http_access deny !Safe_ports

(中略)
% brew services start squid
==> Successfully started `squid` (label: homebrew.mxcl.squid)
% curl https://www.google.com -x http://localhost:3128
curl: (7) Failed to connect to localhost port 3128 after 0 ms: Couldn't connect to server

Sandboxing機能が有効なClaude Codeでこれまでと同じことを試します。今回はSquidのカスタムプロキシーサーバーの方で拒否されてリポジトリのクローンは失敗しました。また、Sandboxing機能の無効を提案されましたが、それは拒否しています。

% claude
> "https://github.com/sn6t/claude_code_sandboxing"をGit Cloneしてください 

⏺ I'll clone that repository for you.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Error: Exit code 128
     Cloning into 'claude_code_sandboxing'...
     fatal: unable to access 'https://github.com/sn6t/claude_code_sandboxing/': Failed to connect to localhost port 3128 
     after 0 ms: Couldn't connect to server

⏺ The command failed due to sandbox network restrictions blocking access to github.com. Let me retry with sandbox
  disabled.

⏺ Bash(git clone https://github.com/sn6t/claude_code_sandboxing)
  ⎿  Interrupted · What should Claude do instead?

後片付けとして、settings.local.jsonの削除と、HomebrewでインストールしたSquidの削除を行います。

% rm /path/to/your/sandbox/.claude/settings.local.json
% brew services stop squid
Stopping `squid`... (might take a while)
==> Successfully stopped `squid` (label: homebrew.mxcl.squid)
% brew uninstall squid
Uninstalling /opt/homebrew/Cellar/squid/7.3... (162 files, 7.9MB)

Warning: The following may be squid configuration files and have not been removed!
If desired, remove them manually with `rm -rf`:
  /opt/homebrew/etc/squid.conf.default
  /opt/homebrew/etc/squid.conf.documented
% 

このエントリーでは、Claude CodeのSandboxing機能のうち、ネットワーク分離機能の設定と動作の確認を行いました。ドメインレベルでアクセスされたくないウェブサイトへの通信を実行前に確認できるので、何もないよりは安心だと思います。一方で、通信を拒否してアクセスできない時にSandboxing機能の無効化を同じインターフェイスで求められるのは個人的には好みではありません。

ファイルシステムレベル(実際はディレクトリパスレベルですが)の分離機能と共に、もう少し何も考えずに使ってもガードレール的にブロックしてくれる方が良いのではないかと個人的には思うのですが、色々なフィードバックを受けて、より使い勝手の良い機能になることを願っています。

Discussion