IPv6ドメイン許可リストの書き方 — Claude Codeサンドボックス
サンドボックスのallowedDomainsとinjectHostsは、IPv6アドレスの書式が別々です。ブラケット表記の書き方と、あいまいな表記をclaude doctorで見つける手順をまとめました。
Claude Codeのサンドボックスは、network.allowedDomainsやnetwork.deniedDomainsに書いたドメインだけへ通信を許可します。設定例の大半はホスト名か、せいぜいIPv4アドレスまでで、IPv6リテラルの書き方に触れているものはほとんどありません。IPv6アドレスをこの許可リストに書くには、ブラケットで囲む専用の書式が必要です。書式を誤ると、許可したつもりの宛先がサンドボックス内から到達できないまま残ります。
サンドボックスのドメイン許可リストがIPv4前提でつまずく理由
サンドボックス化されたBashコマンドは、既定でどのドメインも許可されていません。コマンドが新しいドメインへ接続しようとすると、Claude Codeは承認を求めるか、auto modeでは分類器の判定に回します。ここで「はい、今後は聞かない」を選ぶと、その宛先はWebFetch(domain:...)という許可ルールとしてローカル設定に保存され、以後のセッションでも許可され続けます。承認プロンプトでIPv6アドレスを許可した場合、このルールはブラケット付きの形で保存されます。
この仕組み自体はIPv4アドレスでもホスト名でも変わりません。ただしIPv6アドレスは:を含むため、そのまま書くとポート番号との境界があいまいになります。example.com:443ならコロンの前後がホスト名とポートだと一目で分かりますが、::1:443は「::1というIPv6アドレスにポート443」とも「::1:443という1つのIPv6アドレス」とも読めます。ホスト名の書式をそのままIPv6アドレスへ流用できない理由はここにあります。
ブラケット表記がIPv6アドレスの正しい書き方
サンドボックスのドメインリスト(allowedDomains、deniedDomains、そしてこれらを補うWebFetch(domain:...)ルール)でIPv6アドレスを指定するときは、アドレスをブラケットで囲みます。"[::1]"はそのアドレスへの全ポートに一致し、"[::1]:443"はポート443だけに絞り込みます。ポート番号は先頭ゼロなしの1〜65535の数値で書きます。このブラケット表記はClaude Code v2.1.229以降が必要です。
{
"sandbox": {
"enabled": true,
"network": {
"allowedDomains": ["[2001:db8::1]", "[::1]:443", "registry.npmjs.org"]
}
}
}v2.1.229より前のバージョンでは、ブラケットなしのエントリの末尾コロン以降がポート番号として読める文字列であれば、Claude Codeはそれをポートとして解釈していました。つまり::1:443は「::1のポート443」という意味になり、IPv6アドレス全体としては読まれません。この挙動を知らずに古い設定例をそのまま持ち込むと、意図と違う宛先が許可される可能性があります。
allowedDomainsとinjectHostsは書式が違う
見落としやすいのは、サンドボックス内に複数あるIPv6の書式ルールがリストごとに別々だという点です。認証情報をmode: "mask"で保護する設定にはinjectHostsという別のリストがあり、実値をどの宛先へ送ってよいかを列挙します。この2つのリストは、同じIPv6アドレスでも異なる形式で照合します。
| リスト | 書式 | 例 |
|---|---|---|
network.allowedDomains / deniedDomains | 書式ブラケット表記(正規化形) | 例"[::1]" |
credentials.envVars[].injectHosts | 書式ブラケットなしの正準圧縮形 | 例"::1" / "2001:db8::1" |
injectHostsは、接続先の生のアドレスをそのまま照合するため、ブラケット付きの表記やゾーンID付き、あるいは圧縮の仕方が違う表記を書いても一致しません。allowedDomains用にブラケット表記のIPv6アドレスをそのままinjectHostsへコピーすると、二度と一致しないエントリができあがります。Claude Codeはこの状態をclaude doctorで検出し、「Sandbox credential injectHosts entries can never match their destination」という警告を出します(この検査はv2.1.229以降が必要です)。認証情報のマスキング設定そのものは別記事のClaude Codeの認証情報マスキングをサンドボックスで設定する方法で扱っているので、maskの使い方まで知りたい場合はそちらを参照してください。
あいまいな表記はallowリストとdenyリストで挙動が違う
コロンを2つ以上含むブラケットなしのエントリは、複数の読み方ができてしまいます。::1:443は「::1というアドレス丸ごと」とも「::1のポート443」とも解釈できるため、Claude Codeはどちらか一方を推測するのではなく、リストの性質に応じて安全側に倒します。
- denyリスト: エントリが解釈できるすべての読み方を拒否します。どちらの意味で書いたつもりでも、両方ブロックされます。解釈できる読み方が1つもないエントリは、何もブロックしません
- allowリスト: 書いた範囲より広く許可することは絶対にしません。ホストとポートの読み方としてきれいに解釈できるときはその読み方へ書き換え、それもできない場合はエントリそのものを許可リストから外します
denyリストは「疑わしきは拒否」、allowリストは「疑わしきは許可しない」という、それぞれ逆方向の安全側設計です。困るのは、どちらの実害もエラーを出さずに起きることです。denyのつもりが両方ブロックされて過剰に遮断されるか、allowのエントリが黙って落とされて宛先に到達できないかのどちらかで、警告は表示されません。
具体的に::1:8080という1つのエントリで考えると、読み方は2通りあります。1つは「::1というアドレスの8080番ポート」、もう1つは「::1:8080という値そのものを持つIPv6アドレス」です。deny側にこのエントリを書くと、両方の読み方が同時にブロック対象になります。一方allow側に同じエントリを書くと、Claude Codeは安全に解釈できる「ホストとポート」の読み方だけへ書き換えて許可し、もう一方の読み方は決して許可に含めません。書き換えすら安全にできないと判断すれば、エントリごと許可リストから外します。結果として、denyとallowで同じ文字列を書いても、実際に効く範囲は一致しません。あいまいな表記に頼らず、最初からブラケット表記で書き切ることが、この食い違いを避ける一番確実な方法です。
claude doctorで不安定な表記を洗い出す
claude doctorをターミナルで実行すると、こうした不安定な表記を機械的に見つけられます。
claude doctor「Sandbox network domain entries have unreliable spellings」という警告は、該当エントリを最大3件まで名指しし、残りは件数だけをまとめて表示します。この警告が拾うのはコロンのあいまいさだけではありません。@を含む表記、パスやクエリ文字を含む表記、ブラケットの中にワイルドカードを書いた表記も、同じ警告の対象です。警告に出たエントリは、ブラケット表記へ書き直すことで解消できます。
実務で効いてくる場面
IPv4だけを想定した設定例が多いのは、多くの開発環境がIPv4アドレスかホスト名だけで完結するからです。IPv6が絡んでくるのは、デュアルスタック構成の社内ネットワーク、IPv6アドレスを割り当てるVPCエンドポイントやKubernetesのPod、あるいはIPv6のみでリッスンするセルフホストのプロキシやレジストリにサンドボックスから到達させたい場合です。こうした環境でサンドボックスを有効にすると、ドメイン許可リストにIPv6アドレスを書く必要が出てきます。IPv6が既定で有効なクラウド環境やコンテナ基盤を使い、なおかつサンドボックスも有効にしている構成でだけ意味を持つ、やや上級者向けの設定です。
こうした環境ではホスト名の解決自体が社内DNSに依存していることが多く、DNSが引けない状態でサンドボックスを起動すると、ホスト名を使わずアドレスを直接許可リストに書くしか選択肢がなくなります。IPv6アドレスの書式を先に押さえておくと、DNS障害時の切り分けでも迷いません。
よくある質問
injectHostsにブラケット表記のIPv6アドレスを書くとどうなりますか
一致しません。injectHostsはブラケットなしの正準圧縮形でしか照合しないため、"[::1]"と書いても"::1"という接続先には一致せず、認証情報は注入されません。claude doctorがこの不一致を検出して警告します。
v2.1.229より前のバージョンで::1だけを書くとどう解釈されますか
ブラケット表記が使えないバージョンでは、末尾コロン以降がポート番号として読める場合、Claude Codeはそれをポートとして解釈していました。::1のように末尾がポートとして読めない形であれば、アドレス全体として扱われます。
ポート番号の書式に制限はありますか
先頭ゼロなしの1〜65535の数値である必要があります。"[::1]:0443"のような先頭ゼロ付きの表記は、ポート番号として正しく解釈されません。
allowedDomainsとdeniedDomainsの両方でブラケット表記が必要ですか
必要です。この2つとWebFetch(domain:...)ルールは同じ書式を共有しており、IPv6アドレスはすべてブラケットで囲んで書きます。ブラケットが必要なのはこの3つのリストで、injectHostsだけが別の書式を使います。
まとめ
サンドボックスのドメイン許可リストにIPv6アドレスを書くときは、"[::1]"のようにブラケットで囲みます。ポートを指定するなら"[::1]:443"で、先頭ゼロなしの1〜65535の数値を使います。認証情報マスキングのinjectHostsは同じIPv6アドレスでもブラケットなしの正準圧縮形で照合するため、2つのリストを混同すると片方が静かに機能しなくなります。設定後はclaude doctorを実行し、「Sandbox network domain entries have unreliable spellings」の警告が出ていないかを確認すると、あいまいな表記を通信の失敗より前に見つけられます。IPv4だけの環境なら気にする必要はありませんが、デュアルスタックの社内ネットワークやIPv6のPod・エンドポイントにサンドボックスから到達させる構成では、書式を最初から正しく合わせておく価値があります。