Claude Codeのsandboxでgit SSHだけ失敗する原因と対処(macOS)
macOSのsandbox内でgit fetch・pull・pushがSSHリモートだけ失敗する理由と、HTTPSへの切り替え・excludedCommandsの2つの対処、Linux/WSL2で通らないときの確認点をまとめます。
macOSでsandboxを有効にしたClaude Codeにgit fetch、git pull、git pushを実行させると、SSHのリモートだけが失敗します。接続先をallowedDomainsに入れていても同じです。
原因は、gitのSSH接続がsandboxのプロキシを通る経路で、macOS側のトンネルがそのプロキシに認証できないことにあります。対処は2つあります。リモートをHTTPSに変えるか、gitのネットワークコマンドだけをsandbox外で実行させるかです。
症状:SSHのリモートだけが止まる
失敗するのは、リモートURLがgit@git.example.com:example-org/example-repo.gitのようなSSH形式のときです。https://形式のリモートは、ホストを許可すれば同じ環境でも通ります。
Linux・WSL2との違いは次のとおりです。
| 環境 | SSHリモートのgit fetch / pull / push |
|---|---|
| macOS | SSHリモートのgit fetch / pull / pushホストを許可しても失敗する |
| Linux・WSL2 | SSHリモートのgit fetch / pull / pushホストを許可すれば通る |
macOSで同じ設定のままSSHだけ落ちるなら、設定ミスよりこの組み合わせを疑う場面です。次のエラー文言は、git固有のものではなく、プロキシの環境変数を読まないツール全般が落ちるときのものとして、sandboxingのページに載っています。macOSではOperation not permittedかCould not resolve hostのような名前解決エラー、Linux・WSL2ではNetwork is unreachableかTemporary failure in name resolutionです。
プロキシを読むツールは、落ち方が違います。ホストが許可されていなければ、ネットワークの許可を求めるプロンプトが出るか、プロキシから403が返ります。許可済みのホストなのに名前解決やOperation not permittedで落ちるなら、プロキシをそもそも経由していない側の失敗です。この違いが、原因が許可設定なのか経路なのかを見分ける手がかりになります。
なぜSSHだけ失敗するのか
sandbox内のコマンドには、ネットワークへの直接の経路がありません。macOSではSeatbeltが、sandboxプロキシへの接続以外をふさぎます。外へ出られるのは、HTTP_PROXYやALL_PROXYなどの環境変数でプロキシへ向かうツールだけです。
curlやnpm、HTTPS経由のgitはこの環境変数を読むので、ホストを許可すれば通ります。素のsshはこの環境変数を無視する側にいるため、許可済みのホストにも届きません。
gitのSSHは、そこへ手当てがある例外です。Claude CodeはgitのSSH接続を、sandboxプロキシ経由のトンネルに載せます。Linux・WSL2ではこのトンネルが機能し、macOSではトンネルがプロキシへの認証に失敗します。SSH鍵やホストの許可とは別の層で止まっています。
対処1:リモートをHTTPSに切り替える
sandboxを保ったまま直すなら、リモートURLをHTTPSに変えます。まず現在のリモートを確かめ、git@で始まるSSH形式ならset-urlで差し替えます。
git remote -v
git remote set-url origin \
https://git.example.com/example-org/example-repo.git
git remote -v2回目のgit remote -vで、fetchとpushの両方がhttps://になっていれば切り替えは済みです。HTTPSのリモートには、個人アクセストークンなどHTTPS用の認証情報が必要です。SSH鍵はそのまま使えません。トークンを用意したら、ホストがallowedDomainsに入っていることを確認します。
{
"sandbox": {
"network": {
"allowedDomains": ["git.example.com"]
}
}
}ポートを書かないエントリは、そのホストの全ポートを許可します。HTTPSなら"git.example.com:443"と書いて443だけに絞っても足ります。設定を保存したら、Claude Codeにsandbox内でgit fetchを実行させます。通れば、経路とトークンの両方が揃っています。許可を求めるプロンプトが出る場合は、ホストがallowedDomainsに入っていません。
対処2:gitのネットワークコマンドだけsandbox外で動かす
SSHリモートを維持する必要があるなら、excludedCommandsにgit fetch、git pull、git pushを入れます。
{
"sandbox": {
"excludedCommands": ["git fetch *", "git pull *", "git push *"]
}
}git push origin mainのような呼び出しに、このパターンは一致します。設定キーの書式や置き場所はsandbox.excludedCommandsの解説にまとめています。ここでは、この用途で踏みやすい点だけを挙げます。
- 末尾の
*が要ります。引数なしのgit pushにしか一致しない書き方では、git push origin mainを拾えません cdを足した呼び出しはsandboxに残ります。cd repo && git pushのようにcdを含むと、呼び出し全体がsandbox内で動き、また失敗しますgit -C <dir> pushも残ります。サブコマンドの前にフラグが入る形は、除外の対象になりません- コマンド置換を含む呼び出しも残ります。
$(...)を含むと、呼び出し全体がsandbox内のままです
excludedCommandsで外したgitは、allowedDomainsの外のホストにも届きます。ネットワークの制限が外れた状態でgitが動くので、許可を絞っているつもりでgit push *を入れると、その境界は消えます。除外が効かない呼び出しの形はexcludedCommandsが効かない3つの原因に、Issueの報告つきで整理してあります。
書いたのに効かないときは設定の置き場所も見る
組織のsandboxがadmin-required(管理者必須)の状態だと、.claude/settings.jsonと.claude/settings.local.jsonのexcludedCommandsは無視されます。クローンしたリポジトリがコマンドをsandboxの外へ出せないようにするためです。この場合は~/.claude/settings.jsonに書きます。管理設定側がこのキーを握っている場合は、そちらの変更が必要です。
どちらを選ぶか
| 観点 | HTTPSに切り替え | excludedCommandsで外す |
|---|---|---|
| sandboxの保護 | HTTPSに切り替え保たれる | excludedCommandsで外すgitのネットワーク通信だけ外れる |
| 必要なもの | HTTPSに切り替えHTTPS用の認証情報 | excludedCommandsで外す設定の追記のみ |
| 届く範囲 | HTTPSに切り替えallowedDomains内のホスト | excludedCommandsで外す任意のホスト |
| 呼び出しの形 | HTTPSに切り替え影響なし | excludedCommandsで外すcd・git -Cなどで効かなくなる |
SSH鍵の運用が組織で固定されていなければ、HTTPSへの切り替えのほうが副作用は小さく済みます。リモートを変えられない場合にexcludedCommandsを選ぶ、という順序です。
excludedCommandsに入れたコマンドも、通常の権限フローを通ります。読み取り専用のコマンドや許可ルールが覆うコマンドはプロンプトなしで動き、それ以外は確認が出ます。git pushのような書き込みを毎回確認したいなら、権限側のaskルールと組み合わせる形になります。
Linux・WSL2で通らないときの確認点
Linux・WSL2ではホストを許可すれば動くはずです。それでも失敗するなら、次の3点を順に見ます。
- ホストがポート22で許可されているかを見ます。ポートを書かない
allowedDomainsのエントリ("git.example.com")は全ポートを覆うので、これで足ります。:443だけに絞ったエントリは、ポート22を許可しない書き方です - 社内プロキシがポート22を通すかを見ます。外へ出るために上流プロキシが必要なネットワークでは、トンネルもそのプロキシを通ります
- 鍵がファイルとして読めるかを見ます。sandboxは
ssh-agentのソケットをふさぐことがあります。denyReadやcredentialsで~/.sshを隠していると、鍵ファイルも読めません
3点目は、セキュリティのために入れた設定が原因になる場面です。次のようなcredentialsの設定があると、SSHの鍵が見えなくなります。
{
"sandbox": {
"credentials": {
"files": [{ "path": "~/.ssh", "mode": "deny" }]
}
}
}このときは、~/.sshの拒否を外すか、HTTPSとトークンの組み合わせに切り替えるかを選びます。denyReadの書き方はsandbox.filesystem.denyReadの解説で読めます。
allowUnixSocketsはmacOS専用の設定で、SSHエージェントのソケットを通す用途に使えます(allowUnixSocketsの解説)。ただしこの症状の対処としては、sandboxingのページに挙がっていません。
素のssh・scp・rsyncも同じ理由で落ちる
gitだけでなく、ssh、scp、SSH経由のrsyncも、sandbox内では同じ理由で失敗します。これらはプロキシ環境変数を読まないので、許可済みのホストでも接続できません。
対処はexcludedCommandsで、その呼び出しを外に出すことです。スクリプトを丸ごと外すなら、askルールを添えて毎回承認を挟む例がsandboxingのページに示されています。
{
"sandbox": {
"excludedCommands": ["bash scripts/deploy.sh *"]
},
"permissions": {
"ask": ["Bash(bash scripts/deploy.sh *)"]
}
}除外されたスクリプトはフルアクセスで動きます。作業ディレクトリの中にあるスクリプトはClaudeが編集できるので、承認のプロンプトが出たときに中身を見る運用になります。
SSHのgitが失敗したときの切り分け
- QmacOSですか?答えがLinux・WSL2の確認点(ポート22・上流プロキシ・鍵の読み取り)へ答えがはい
HTTPSへの切り替えか、
excludedCommandsのどちらかを選びます。 - QリモートをHTTPSに変えられますか?答えがexcludedCommandsにgit fetch・pull・pushを入れる答えがはい
git remote set-urlで変え、ホストをallowedDomainsに入れます。
sandboxを保ったままgitが通る
トークンなどHTTPS用の認証情報を用意して、git fetchを実行し直します。
症状がgit以外にもあるとき
git addが止まる場合は、ネットワークではなく保護パスの置き場が原因の別問題です。Claude Codeのsandboxでgit addが失敗する原因と回避策で扱っています。sandboxに止められたコマンドをその場で外へ出す再実行の仕組みは、allowUnsandboxedCommandsの解説にあります。ただし再実行は承認を挟む前提の逃げ道で、恒常的な解決にはなりません。
まとめ
macOSのsandboxでSSHのgitだけが落ちるのは、トンネルの認証という層で止まっているからで、allowedDomainsをいくら足しても変わりません。HTTPSにして保護を残すか、excludedCommandsでgit通信を外に出して境界を緩めるかの2択です。Linux・WSL2では、ポート22の許可・上流プロキシ・~/.sshの隠し方の3点を見れば、原因はほぼ絞れます。