Skip to content

fetch() fails with UNABLE_TO_GET_ISSUER_CERT_LOCALLY while curl and openssl validate the same HTTPS endpointΒ #62690

@kevgeoleo

Description

@kevgeoleo

Version

24.13.1

Platform

Linux KContainer 5.10.0-12-amd64 #1 SMP Debian 5.10.103-1 (2022-03-07) x86_64 x86_64 x86_64 GNU/Linux

Subsystem

No response

What steps will reproduce the bug?

Hi,

I would like to report a behavior in Node that can be reproduced using the below PoC:

const req = new Request("https://example.org");

const init = {
  method: "GET",
};

req.headers.set("foo", "bar");

const res = await fetch(req, init);

console.log("Status:", res.status);

How often does it reproduce? Is there a required condition?

No specific condition

What is the expected behavior? Why is that the expected behavior?

Works in Deno and Bun

root@KContainer:~/10396# deno run -A main.mjs
Status: 200
root@KContainer:~/10396# bun run main.mjs
Status: 200

Using curl works

root@KContainer:~/10396# curl -v https://example.org
*   Trying 104.20.26.136:443...
* Connected to example.org (104.20.26.136) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
*  CAfile: /etc/ssl/certs/ca-certificates.crt
*  CApath: /etc/ssl/certs
* TLSv1.0 (OUT), TLS header, Certificate Status (22):
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS header, Certificate Status (22):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS header, Finished (20):
* TLSv1.2 (IN), TLS header, Supplemental data (23):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.2 (OUT), TLS header, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS header, Supplemental data (23):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN, server accepted to use h2

What do you see instead?

Fetch fails due to UNABLE_TO_GET_ISSUER_CERT_LOCALLY

root@KContainer:~/10396# node main.mjs
node:internal/deps/undici/undici:16416
      Error.captureStackTrace(err);
            ^

TypeError: fetch failed
    at node:internal/deps/undici/undici:16416:13
    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
    at async file:///10396/main.mjs:9:13 {
  [cause]: Error: unable to get local issuer certificate
      at TLSSocket.onConnectSecure (node:internal/tls/wrap:1649:34)
      at TLSSocket.emit (node:events:508:28)
      at TLSSocket._finishInit (node:internal/tls/wrap:1094:8)
      at ssl.onhandshakedone (node:internal/tls/wrap:880:12) {
    code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'
  }
}

Node.js v24.13.1
root@KContainer:~/10396# node -e "fetch('https://example.org').then(r=>console.log(r.status)).catch(console.error)"
TypeError: fetch failed
    at node:internal/deps/undici/undici:16416:13
    at process.processTicksAndRejections (node:internal/process/task_queues:103:5) {
  [cause]: Error: unable to get local issuer certificate
      at TLSSocket.onConnectSecure (node:internal/tls/wrap:1649:34)
      at TLSSocket.emit (node:events:508:28)
      at TLSSocket._finishInit (node:internal/tls/wrap:1094:8)
      at ssl.onhandshakedone (node:internal/tls/wrap:880:12) {
    code: 'UNABLE_TO_GET_ISSUER_CERT_LOCALLY'
  }
}

Additional information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    tlsIssues and PRs related to the tls subsystem.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions