Claude Media
Claude Codeのsandboxでgit SSHだけ失敗する原因と対処(macOS)

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
macOSSSHリモートのgit fetch / pull / pushホストを許可しても失敗する
Linux・WSL2SSHリモートの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 -v

2回目の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点を順に見ます。

  1. ホストがポート22で許可されているかを見ます。ポートを書かないallowedDomainsのエントリ("git.example.com")は全ポートを覆うので、これで足ります。:443だけに絞ったエントリは、ポート22を許可しない書き方です
  2. 社内プロキシがポート22を通すかを見ます。外へ出るために上流プロキシが必要なネットワークでは、トンネルもそのプロキシを通ります
  3. 鍵がファイルとして読めるかを見ます。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が失敗したときの切り分け

  1. QmacOSですか?
    答えがLinux・WSL2の確認点(ポート22・上流プロキシ・鍵の読み取り)へ

    HTTPSへの切り替えか、excludedCommandsのどちらかを選びます。

    答えがはい
  2. 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点を見れば、原因はほぼ絞れます。

この記事を共有:XはてブLinkedIn