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 への直接代入も避け、コマンドラインから一時的に渡します。
実行例
実際に上記の手順を node:20(Debian GNU/Linux 12 bookworm / Node.js v20.20.2 / OpenSSL 3.0.19)環境で動かすと、CA を追加しない素の fetch では本記事のエラーメッセージ self-signed certificate in certificate chain に対応するエラーコード SELF_SIGNED_CERT_IN_CHAIN(err.cause.code)が発生し、NODE_EXTRA_CA_CERTS を指定した場合は HTTP 200 が返ることが確認できます。
$ node -v
v20.20.2$ openssl version
OpenSSL 3.0.19 27 Jan 2026 (Library: OpenSSL 3.0.19 27 Jan 2026)
CA 作成の終了コード: 0
署名の終了コード: 0$ node server.js
HTTPS サーバ起動: https://localhost:8443$ node client.js
失敗: SELF_SIGNED_CERT_IN_CHAIN
終了コード: 0$ NODE_EXTRA_CA_CERTS=./ca-cert.pem node client.js
status: 200 body: ok
終了コード: 0$ NODE_TLS_REJECT_UNAUTHORIZED=0 node client.js
(node:98) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
status: 200 body: ok
終了コード: 0— 2026-08-02 時点の出力