Pular para o conteúdo
ecdsa.com
Node.js tls / https / fetchMódulo crypto do Node.js

Mensagem de erro

unable to verify the first certificate

Também aparece como

  • code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
  • UNABLE_TO_VERIFY_LEAF_SIGNATURE

Versões recentes do Node.js (24.22 no nosso teste) acrescentam “; if the root CA is installed locally, try running Node.js with --use-system-ca” a esta mensagem. Com fetch(), ela aparece como a causa de “TypeError: fetch failed”; o axios e o got a exibem como a mensagem de erro, com o mesmo código.

Node.js tls / https / fetch — code UNABLE_TO_VERIFY_LEAF_SIGNATURE (OpenSSL X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE, 21)

O que significa

O Node.js recebeu só o certificado do próprio servidor (o certificado folha) e não encontrou o emissor dele em lugar nenhum: nem no handshake, nem entre as raízes confiáveis. Sem o emissor, ele não consegue nem verificar a assinatura do certificado folha — daí “the first certificate”. Quase sempre o servidor deixa de enviar o certificado intermediário; os navegadores mascaram o problema baixando os intermediários, mas o Node.js nunca faz isso.

Por que acontece

Como corrigir

  1. 1.

    Verificar quantos certificados o servidor envia

    Se aparecer só a profundidade 0 e o emissor desse certificado for uma CA intermediária, a correção deve ser feita no servidor.

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

    Servir a cadeia completa

    Configure o servidor com um bundle que tenha o certificado folha seguido de todos os intermediários. Em servidores Node.js, é a opção cert; no nginx, ssl_certificate; em balanceadores de carga na nuvem, o campo da cadeia de certificados.

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

    Se não puder alterar o servidor: adicionar o intermediário no cliente

    A variável NODE_EXTRA_CA_CERTS também aceita certificados intermediários e é lida uma vez, na inicialização do processo. Prefira corrigir o servidor: todos os outros clientes (aplicativos móveis, parceiros) têm o mesmo problema.

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

    Diagnóstico temporário: desativar a verificação em uma execução

    NODE_TLS_REJECT_UNAUTHORIZED=0 desliga as verificações de certificado em todas as conexões TLS do processo e imprime um aviso. Use apenas para confirmar o diagnóstico; em produção, isso permite que qualquer um no caminho leia e altere o tráfego.

    bash
    # Temporary diagnostic only: disables certificate verification for the whole process
    NODE_TLS_REJECT_UNAUTHORIZED=0 node app.js

Erros relacionados

Ver toda a base de erros de assinatura