Node.js で fetch が「self-signed certificate in certificate chain」で接続できない
Node.js 組み込み fetch は OpenSSL の信頼ストアで TLS チェーンを検証するため、社内 CA や自己署名証明書を挟んだ環境では接続できません。
`NODE_EXTRA_CA_CERTS` で追加 CA を読み込ませるのが安全な対処で、`NODE_TLS_REJECT_UNAUTHORIZED=0` は検証を完全に切ってしまうため本番では使いません。
公開:
要約
Node.js 組み込み fetch は OpenSSL の信頼ストアで TLS チェーンを検証するため、社内プロキシや MITM 装置で挿入された自己署名 CA を信頼していない環境では self-signed certificate in certificate chain で接続できません。NODE_EXTRA_CA_CERTS で追加 CA を読み込ませるのが安全な対処で、NODE_TLS_REJECT_UNAUTHORIZED=0 は検証を完全に切ってしまうため本番では使いません。
よくある原因
- 社内プロキシや MITM 装置が挿入する自己署名 CA が Node.js の信頼ストアに入っていない
- サーバが中間 CA を返しておらず、不完全なチェーンになっている
- Node.js は独自の CA バンドルを内蔵し、OS の信頼ストアを自動では参照しない
- Docker / CI で
/etc/ssl/certsをマウントしていない、またはca-certificatesが古い
解決策
1. CA を環境変数で追加する(推奨)
社内 CA の PEM ファイルを NODE_EXTRA_CA_CERTS で指定すると、Node 内蔵バンドルに 追加 して信頼します(公式ドキュメント)。
export NODE_EXTRA_CA_CERTS=/etc/ssl/private/corp-root-ca.pem
node app.js複数 CA が必要なら同じ PEM ファイル内に連結します。
2. OS の信頼ストアを使う
Node.js 22 以降では --use-system-ca で OS の信頼ストアを参照できます。
社員 PC に CA が配布されている環境ではこちらが楽です。
node --use-system-ca app.js
# あるいは
NODE_OPTIONS="--use-system-ca" node app.js3. undici Agent で CA を渡す
特定のリクエストだけ別 CA を使いたい場合は undici の Agent を組み立てて fetch に渡します。
import { Agent, fetch } from "undici";
import { readFileSync } from "node:fs";
const agent = new Agent({
connect: { ca: readFileSync("./corp-ca.pem") },
});
const res = await fetch("https://internal.example.com/", { dispatcher: agent });4. 開発検証時のみ検証を切る
NODE_TLS_REJECT_UNAUTHORIZED=0 node debug.jsこのフラグはプロセス全体で TLS 検証を無効化するため、CI / 本番では使わないでください。process.env への直接代入も避け、コマンドラインから一時的に渡します。