Сообщение об ошибке
self-signed certificate in certificate chain
Также выводится как
- code: 'SELF_SIGNED_CERT_IN_CHAIN'
- SELF_SIGNED_CERT_IN_CHAIN
Node.js 16 и более ранние версии (OpenSSL 1.1.1) писали «self signed certificate in certificate chain». При вызове fetch() это сообщение указывается как причина ошибки «TypeError: fetch failed»; npm выводит его как «npm error code SELF_SIGNED_CERT_IN_CHAIN».
Node.js tls / https / fetch — code SELF_SIGNED_CERT_IN_CHAIN (OpenSSL X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN, 19)
Что это означает
Цепочка, которую отправил сервер, заканчивается самоподписанным корневым сертификатом, которого нет в списке доверенных корневых сертификатов Node.js. В корпоративной сети это характерный признак прокси с инспекцией TLS: он переподписывает каждый сайт собственным корневым сертификатом и включает этот корневой сертификат в цепочку. Node.js использует встроенный список корневых сертификатов Mozilla, а не хранилище операционной системы, куда ИТ-отдел установил корневой сертификат прокси.
Почему это происходит
Прокси или антивирус с инспекцией TLS
частоZscaler, Netskope, Fortinet, Palo Alto и антивирусы, сканирующие HTTPS, предъявляют собственный корневой сертификат. Браузеры доверяют ему через хранилище ОС, а Node.js по умолчанию — нет.
Частный сервис отправляет собственный корневой сертификат
частоДаже если внутренние серверы включают корневой сертификат компании в цепочку, клиент всё равно должен доверять этому корневому сертификату: сама отправка ничего не доказывает.
Корневой сертификат установлен в ОС, но Node.js использует свой список
иногдаNode.js поставляется с корневыми сертификатами Mozilla внутри исполняемого файла и игнорирует системное хранилище, если не задан --use-system-ca или NODE_USE_SYSTEM_CA=1.
Как исправить
- 1.
Посмотрите, кто выпустил цепочку
Пройдите по цепочке сертификатов, которую отдаёт публичный сайт. Если верхний сертификат назван по имени вашей компании или поставщика средств защиты, добавьте этот корневой сертификат в доверенные; если имя незнакомое, разберитесь, прежде чем чему-либо доверять.
bash openssl s_client -connect registry.npmjs.org:443 -servername registry.npmjs.org -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' # The last line pair shows the root the chain ends in (s: and i: identical) - 2.
Добавьте корневой сертификат через NODE_EXTRA_CA_CERTS
Сертификаты из файла добавляются к встроенным корневым сертификатам для каждого TLS-соединения процесса, включая npm, yarn и fetch. Задайте переменную до запуска процесса.
bash export NODE_EXTRA_CA_CERTS=/etc/ssl/private-ca/corp-proxy-root.pem node app.js - 3.
Используйте хранилище операционной системы
С --use-system-ca или NODE_USE_SYSTEM_CA=1 Node.js принимает корневые сертификаты, которым доверяет ОС, поэтому корневой сертификат прокси, развёрнутый ИТ-отделом, работает без копирования файлов.
bash # Managed machines already trust the proxy root in the OS store node --use-system-ca app.js NODE_USE_SYSTEM_CA=1 npm run build - 4.
Временная диагностика: NODE_TLS_REJECT_UNAUTHORIZED=0
Переменная отключает проверку сертификатов во всём процессе. Используйте её только на один запуск, чтобы подтвердить причину; за перехватывающим прокси она к тому же скрывает любого злоумышленника, кроме самого прокси.
bash # Temporary diagnostic only: confirms trust is the only problem, then remove it NODE_TLS_REJECT_UNAUTHORIZED=0 node app.js