Сообщение об ошибке
unable to verify the first certificate
Также выводится как
- code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
- UNABLE_TO_VERIFY_LEAF_SIGNATURE
Последние релизы Node.js (24.22 в нашей проверке) добавляют к этому сообщению «; if the root CA is installed locally, try running Node.js with --use-system-ca». При вызове fetch() оно указывается как причина ошибки «TypeError: fetch failed»; axios и got показывают его как сообщение об ошибке с тем же кодом.
Node.js tls / https / fetch — code UNABLE_TO_VERIFY_LEAF_SIGNATURE (OpenSSL X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, 21)
Что это означает
Node.js получил только собственный (конечный) сертификат сервера и нигде не нашёл его издателя: ни в рукопожатии, ни среди доверенных корневых сертификатов. Без издателя Node.js не может даже проверить подпись конечного сертификата — отсюда «the first certificate». Почти всегда сервер просто забывает отправить промежуточный сертификат; браузеры маскируют это, скачивая промежуточные сертификаты сами, а Node.js этого никогда не делает.
Почему это происходит
Сервер не отправляет промежуточный сертификат
частоФайл сертификата, в котором только конечный сертификат (cert.pem вместо fullchain.pem или сертификат балансировщика нагрузки, загруженный без цепочки). Даже если нужный корневой сертификат в доверенных, Node.js не может связать конечный сертификат с корневым, как видно из воспроизведения ошибки.
Конечный сертификат выпущен частным CA, и в цепочке нет ни одного известного сертификата
частоВнутренние сервисы, которые отдают без цепочки сертификат от корпоративного или самостоятельно созданного CA, дают тот же код ошибки: Node.js не знает ни издателя, ни того, что выше него.
Промежуточный сертификат есть в файле, но не используется
иногдаНекоторые серверы отправляют только первый сертификат из файла или ожидают цепочку в отдельной настройке (SSLCertificateChainFile в старых версиях Apache, отдельное поле для цепочки в облачных балансировщиках нагрузки). Промежуточный сертификат лежит на диске, но до клиента так и не доходит.
Как исправить
- 1.
Проверьте, сколько сертификатов отправляет сервер
Если виден только сертификат глубины 0, а его издатель — промежуточный CA, исправлять нужно на сервере.
bash openssl s_client -connect api.example.com:443 -servername api.example.com -showcerts </dev/null 2>/dev/null \ | grep -E '^ *[0-9]+ s:|^ *i:' # Only " 0 s:" present, with an i: that is an intermediate -> the server must send that intermediate - 2.
Отдавайте полную цепочку
Передайте серверу файл, в котором за конечным сертификатом следуют все промежуточные. Для серверов на Node.js это параметр cert, для nginx — ssl_certificate, для облачных балансировщиков нагрузки — поле цепочки сертификатов.
js // Node.js HTTPS server: pass leaf + intermediates as the cert import https from "node:https"; import fs from "node:fs"; https.createServer({ key: fs.readFileSync("server.key"), cert: fs.readFileSync("fullchain.pem"), // leaf first, then intermediate(s) }, handler).listen(443); - 3.
Если сервер изменить нельзя, добавьте промежуточный сертификат на клиенте
NODE_EXTRA_CA_CERTS принимает и промежуточные сертификаты; переменная читается один раз при запуске процесса. Но лучше исправить сервер: у всех остальных клиентов (мобильных приложений, партнёров) та же проблема.
bash # When you cannot fix the server: trust the missing intermediate on the client too NODE_EXTRA_CA_CERTS=/etc/ssl/certs/issuing-ca.pem node app.js - 4.
Временная диагностика: отключите проверку на один запуск
NODE_TLS_REJECT_UNAUTHORIZED=0 отключает проверку сертификатов для всех TLS-соединений процесса и выводит предупреждение. Используйте эту переменную только для подтверждения диагноза: в рабочей среде она позволяет любому на пути трафика читать и изменять его.
bash # Temporary diagnostic only: disables certificate verification for the whole process NODE_TLS_REJECT_UNAUTHORIZED=0 node app.js
Связанные ошибки
unable to get local issuer certificateNode.js tls / https / fetchself-signed certificate in certificate chainNode.js tls / https / fetchnpm error code UNABLE_TO_VERIFY_LEAF_SIGNATUREnpm (Node.js)verify error:num=21:unable to verify the first certificateOpenSSL CLI (openssl s_client)curl: (60) SSL certificate problem: unable to get local issuer certificatecurl (OpenSSL backend)