Перейти к содержимому
ecdsa.com
Node.js tls / https / fetchМодуль crypto в Node.js

Сообщение об ошибке

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 доверяет только списку корневых сертификатов Mozilla, встроенному в исполняемый файл, а не хранилищу операционной системы, поэтому корневой сертификат компании, установленный на машине, для него не виден, пока вы не укажете Node.js использовать его.

Почему это происходит

Как исправить

  1. 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. 2.

    Используйте хранилище операционной системы

    С --use-system-ca (или NODE_USE_SYSTEM_CA=1 в окружении) Node.js доверяет тем же сертификатам, что и ОС, а именно их и администрируют ИТ-отделы.

    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. 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. 4.

    Настройте доверие к корневому сертификату для одного агента

    Параметр ca у агента или tls.connect() заменяет корневые сертификаты по умолчанию для этих соединений, поэтому добавьте 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());

Связанные ошибки

Открыть всю базу ошибок подписей