SSL certificate verification failed
TLS証明書の検証に失敗した状態。社内のTLSインスペクション型プロキシが主因。
エラー文字列
SSL certificate verification failed
何が起きているか
接続先の TLS 証明書を検証できず、通信を中止しています。ログイン時や起動時に出ることが多いエラーです。
⚠️ このエラーはリトライされません。 証明書の検証失敗は「待てば直る」種類の問題ではないため、Claude Code は最初の試行で報告して止まります。何度実行しても同じ結果になります。
原因は3つですが、日本の企業ネットワークでは1番が圧倒的に多数です。
| # | 原因 | 典型的な状況 |
|---|---|---|
| 1 | TLSインスペクション型のプロキシ/ファイアウォール | 社内から接続。Zscaler、Netskope、Blue Coat、FortiGate など |
| 2 | CA証明書のバンドルが見つからない | 独自ビルドの環境、コンテナ、最小構成の Linux |
| 3 | 証明書の期限切れ | 自前のプロキシやゲートウェイを立てている場合 |
なぜ社内ネットワークで起きるのか
TLSインスペクションを行う製品は、通信を一度復号して検査し、組織独自の証明書で署名し直してから中継します。ブラウザは組織の証明書があらかじめ配布されているので問題になりませんが、Node.js は OS の証明書ストアを見ないため、そのままでは「知らない発行者」として弾きます。
⭐ 「ブラウザでは claude.ai が普通に開けるのに、Claude Code だけ繋がらない」という状況なら、ほぼこれです。
直し方
1. TLSインスペクションが入っているか確認する
Windows(PowerShell 5.1 でも動きます)
$req = [System.Net.HttpWebRequest]::Create("https://api.anthropic.com")
try { $req.GetResponse() | Out-Null } catch { }
$req.ServicePoint.Certificate.Issuer
証明書の検証に失敗している状態でも発行者を見たい場合は、検証をこの1回だけ素通しにして中身を読みます。
$host_ = "api.anthropic.com"
$tcp = New-Object System.Net.Sockets.TcpClient($host_, 443)
$ssl = New-Object System.Net.Security.SslStream(
$tcp.GetStream(), $false,
({ $true } -as [System.Net.Security.RemoteCertificateValidationCallback]))
$ssl.AuthenticateAsClient($host_)
"Issuer : " + $ssl.RemoteCertificate.Issuer
"Subject: " + $ssl.RemoteCertificate.Subject
$ssl.Dispose(); $tcp.Close()
⚠️ これは発行者を「見るだけ」の確認用です。 検証を無効にしたまま通信するものではありません。
macOS / Linux
openssl s_client -connect api.anthropic.com:443 -servername api.anthropic.com </dev/null 2>/dev/null | openssl x509 -noout -issuer
⭐ Windows でも上のコマンドが使えます。 openssl は PATH に無いことが多いのですが、Git for Windows に同梱されています。 Git Bash を開けばそのまま実行できます。
場所を確認する場合は次のとおりです。
$git = Get-Command git -ErrorAction SilentlyContinue
if ($git) {
$root = Split-Path (Split-Path $git.Source -Parent) -Parent
"openssl: " + (Test-Path "$root\usr\bin\openssl.exe")
}
出力の判定は次のとおりです。
| 発行者 | 判定 |
|---|---|
CN=WE1, O=Google Trust Services, C=US のような公的CA |
インスペクションなし。原因は 2 か 3 |
社名や製品名が入っている(例: CN=YourCompany SSL Inspection) |
TLSインスペクションあり。手順 2 へ |
⭐ インスペクションが無い環境では、上の1つ目のような公的CAの名前が返ります。 ここに見覚えのない社名や製品名が出たら、その機器が通信を復号しています。
2. 組織のCA証明書を Node.js に教える(原因 1)
⚠️ 証明書の検証を無効化しないでください。 一時的には動きますが、通信の中身を誰でも差し替えられる状態になります。正しい対処は「組織の証明書を信頼させる」ことです。
証明書ファイルを入手する
情報システム部門から CA 証明書(.crt / .pem / .cer)を受け取ってください。自分で取り出すこともできます。
Windows の証明書ストアから書き出す場合:
# 「信頼されたルート証明機関」から社名で検索
Get-ChildItem Cert:\LocalMachine\Root | Where-Object { $_.Subject -match "会社名やプロキシ製品名" } |
Select-Object Subject, Thumbprint
該当したものを Base-64 でエクスポートします。
$cert = Get-ChildItem Cert:\LocalMachine\Root\<Thumbprint>
$pem = "-----BEGIN CERTIFICATE-----`n" +
[Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks') +
"`n-----END CERTIFICATE-----"
Set-Content -Path "$env:USERPROFILE\corp-ca.crt" -Value $pem -Encoding ascii
Node.js に読ませる
[Environment]::SetEnvironmentVariable("NODE_EXTRA_CA_CERTS", "$env:USERPROFILE\corp-ca.crt", "User")
macOS / Linux
echo 'export NODE_EXTRA_CA_CERTS=/etc/ssl/certs/corp-ca.crt' >> ~/.zshrc
source ~/.zshrc
設定後、ターミナルを開き直してください。
settings.json に書く場合はパスを指定します。⚠️ 証明書の中身を直接書かないこと(設定ファイルが肥大化し、別のエラーの原因になります)。
{
"env": {
"NODE_EXTRA_CA_CERTS": "C:\\Users\\you\\corp-ca.crt"
}
}
3. 中間証明書が足りていないか確認する
証明書を1枚だけ入れて直らない場合、ルートだけで中間証明書が抜けていることがあります。プロキシ製品によってはチェーンが2〜3段になります。
必要な証明書をすべて1つのファイルに連結してください。
cat corp-root.crt corp-intermediate.crt > corp-bundle.crt
export NODE_EXTRA_CA_CERTS=/path/to/corp-bundle.crt
4. CAバンドルが無い環境(原因 2)
コンテナや最小構成の Linux では、そもそも公的CAのバンドルが入っていないことがあります。
# Debian / Ubuntu
sudo apt-get update && sudo apt-get install -y ca-certificates
sudo update-ca-certificates
# RHEL / Alma / Rocky
sudo dnf install -y ca-certificates
sudo update-ca-trust
5. 検証を無効化する場合(⚠️ 開発時の一時措置のみ)
NODE_TLS_REJECT_UNAUTHORIZED=0 claude
⚠️ この設定は通信の改ざんと盗聴を検知できなくします。
- 恒久設定にしない。 シェルの設定ファイルに書かない
- 業務端末で使わない。 資格情報がそのまま流れます
- 切り分けのために一度だけ試し、原因が確定したら必ず正規の手順(手順 2)に戻す
このフラグで通るなら、原因が証明書チェーンであることの確認にはなります。それ以上の使い道はありません。
再発防止
- 社内ネットワークで開発するなら、
NODE_EXTRA_CA_CERTSは最初に設定しておく。 Claude Code に限らず、Node.js 製のツール全般で同じ問題が起きます - 情報システム部門にPEM形式のCAバンドルを用意してもらい、チームで配布する。各自が証明書を書き出す運用は事故のもとです
- 証明書には期限があります。更新時期を把握しておくと、ある日突然全員が繋がらなくなる事態を避けられます
NODE_TLS_REJECT_UNAUTHORIZED=0を「とりあえず」で残さない。動いてしまうぶん、あとで気づけません