エラーメッセージ
unable to get local issuer certificate
別の表記
- code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'
- UNABLE_TO_GET_ISSUER_CERT_LOCALLY
fetch() では、このメッセージは「TypeError: fetch failed」の原因として現れます。npm は同じ状況を「npm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLY」として報告します。サーバーがリーフ証明書しか送信しない場合、Node.js は代わりに「unable to verify the first certificate」と報告します。
Node.js tls / https / fetch — code UNABLE_TO_GET_ISSUER_CERT_LOCALLY (OpenSSL X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY, 20)
このエラーの意味
サーバーはチェーン(リーフ証明書と中間証明書)を送信しましたが、その最上位の証明書は、Node.js が信頼していないルートによって発行されていました。Node.js はデフォルトで、OS のストアではなく、バイナリに組み込まれた Mozilla のルートリストだけを信頼します。そのため、マシンにインストールされた社内のルートは、Node.js にそれを使うよう指示しない限り、Node.js からは見えません。
発生する理由
社内 CA またはプライベート CA
よくある社内 API、ステージング環境、サービスメッシュでは、Node.js に同梱された Mozilla のリストに含まれていないルートが使われています。
TLS を検査するプロキシ
よくある社内ネットワークでは、通信を傍受するプロキシが、公開サイトの証明書を社内のルートで署名し直します。プロキシが発行元の中間証明書しか送信しない場合、Node.js は「self-signed certificate in certificate chain」ではなく、このコードを報告します。
Node.js はデフォルトで OS のトラストストアを無視する
ときどきupdate-ca-certificates、Windows の証明書ストア、macOS のキーチェーンのいずれかでルートをインストールすると、curl とブラウザーは直りますが、--use-system-ca または NODE_USE_SYSTEM_CA=1 を使わない限り、Node.js は直りません。
修正方法
- 1.
NODE_EXTRA_CA_CERTS
Node.js に PEM ファイルを指定し、そのファイル内の証明書を組み込みのルートに追加します。この変数はプロセスの起動時に一度だけ読み込まれるため、実行中のアプリ内で設定しても効果はありません。
bash # Adds to Node's built-in roots; read once at start-up, so set it before node starts export NODE_EXTRA_CA_CERTS=/etc/ssl/private-ca/corp-root-ca.pem node app.js - 2.
OS の証明書ストアを使う
--use-system-ca(または環境変数の NODE_USE_SYSTEM_CA=1)を指定すると、Node.js は OS が信頼する証明書を信頼するようになります。IT 部門が管理しているのは、まさにこの証明書です。
bash # Trust what the operating system trusts (Windows store, macOS Keychain, Linux bundle) node --use-system-ca app.js # or, for tools that start node themselves (npm scripts, CLIs): NODE_USE_SYSTEM_CA=1 npx some-cli - 3.
コードでデフォルトの CA リストを設定する
tls.setDefaultCACertificates() は、それ以降に https、tls、fetch で確立される接続のデフォルトのリストを置き換えます。例のように、既存のデフォルトと独自のルートを組み合わせてください。
js // In code, before the first request: keep the default roots and add yours. // Applies to https, tls and fetch. Available in current Node.js 22 and 24 releases. import tls from "node:tls"; import fs from "node:fs"; tls.setDefaultCACertificates([ ...tls.getCACertificates("default"), fs.readFileSync("/etc/ssl/private-ca/corp-root-ca.pem", "utf8"), ]); - 4.
1 つのエージェントに限ってルートを信頼する
エージェントまたは tls.connect() の ca オプションは、それらの接続のデフォルトのルートを置き換えます。そのため、同じエージェントが公開ホストとも通信する場合は、tls.rootCertificates も含めてください。
js // Per-agent trust: note that "ca" REPLACES the default roots, so append them import https from "node:https"; import tls from "node:tls"; import fs from "node:fs"; const agent = new https.Agent({ ca: [...tls.rootCertificates, fs.readFileSync("corp-root-ca.pem", "utf8")] }); https.get("https://api.example.com/", { agent }, (res) => res.resume());
関連するエラー
unable to verify the first certificateNode.js tls / https / fetchself-signed certificate in certificate chainNode.js tls / https / fetchnpm error code UNABLE_TO_GET_ISSUER_CERT_LOCALLYnpm (Node.js)[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local…Python ssl module (OpenSSL)