Saltar al contenido
ecdsa.com
Node.js tls / https / fetchcrypto de Node.js

Mensaje de error

unable to verify the first certificate

También se muestra como

  • code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'
  • UNABLE_TO_VERIFY_LEAF_SIGNATURE

Las versiones recientes de Node.js (24.22 en nuestra prueba) añaden «; if the root CA is installed locally, try running Node.js with --use-system-ca» a este mensaje. Con fetch() aparece como la causa de «TypeError: fetch failed»; axios y got lo muestran como mensaje de error con el mismo código.

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

Qué significa

Node.js recibió solo el certificado propio del servidor (el certificado hoja) y no encontró su emisor en ninguna parte: ni en el handshake ni entre sus raíces de confianza. Sin el emisor, ni siquiera puede comprobar la firma del certificado hoja; de ahí lo de «the first certificate». Casi siempre, el servidor olvida enviar su certificado intermedio; los navegadores lo disimulan descargando los intermedios, cosa que Node.js nunca hace.

Por qué ocurre

Cómo solucionarlo

  1. 1.

    Comprobar cuántos certificados envía el servidor

    Si solo aparece la profundidad 0 y su emisor es una CA intermedia, la corrección corresponde al 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 la cadena completa

    Proporciona al servidor un bundle con el certificado hoja seguido de todos los intermedios. En los servidores Node.js es la opción cert; en nginx, ssl_certificate; en los balanceadores de carga en la nube, el campo de la cadena 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.

    Si no puedes cambiar el servidor: añadir el intermedio en el cliente

    NODE_EXTRA_CA_CERTS también acepta certificados intermedios y se lee una sola vez, al arrancar el proceso. Es preferible corregir el servidor: todos los demás clientes (aplicaciones móviles, socios) tienen el mismo 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 temporal: desactivar la verificación en una sola ejecución

    NODE_TLS_REJECT_UNAUTHORIZED=0 desactiva las comprobaciones de certificados en todas las conexiones TLS del proceso y muestra una advertencia. Úsalo solo para confirmar el diagnóstico; en producción permite que cualquiera en la ruta lea y altere el tráfico.

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

Errores relacionados

Explorar toda la base de datos de errores de firma