Home > Software design >  Node retrieving old TLS certificate
Node retrieving old TLS certificate

Time:04-04

I used the following code to get the server TLS certificate for stackoverflow.com:

const tls = require('tls');

const conn = tls.connect({
  host: 'stackoverflow.com',
  port: 443,
  rejectUnauthorized: false
}, () => {
  const cert = conn.getPeerCertificate(false);
  console.log(cert);
  conn.destroy();
});

The result includes the following:

  • subject: { CN: '*.stackexchange.com' }
  • issuer: { C: 'US', O: "Let's Encrypt", CN: 'R3' }
  • valid_from: Dec 3 14:00:52 2020 GMT
  • valid_to: Mar 3 14:00:52 2021 GMT
  • fingerprint256: C6:D3:6E:68:38:EC...

Note that it is an expired certificate.

By contrast, when I visit stackoverflow.com in Firefox, it loads a certificate with the following details:

  • Not before: Sun, 06 Mar 2022 14:17:27 GMT
  • Not after: Sat, 04 Jun 2022 14:17:26 GMT
  • SHA-256: 04:F7:14:2A:28:EF:1F...

It appears Node is obtaining an old certificate. Perhaps it is cached somewhere?

My platform is:

  • Node v17.8.0
  • Linux, x64, Manjaro

CodePudding user response:

I get the same invalid certificate with your original code, so I took a look at the documentation, and it has the following interesting tidbit:

Unlike the https API, tls.connect() does not enable the SNI (Server Name Indication) extension by default, which may cause some servers to return an incorrect certificate or reject the connection altogether. To enable SNI, set the servername option in addition to host.

Adding the servername option:

const tls = require('tls');

const conn = tls.connect({
  host: 'stackoverflow.com',
  servername: 'stackoverflow.com',
  port: 443,
  rejectUnauthorized: false
}, () => {
  const cert = conn.getPeerCertificate(false);
  console.log(cert);
  conn.destroy();
});

I obtain a valid certificate:

subject: [Object: null prototype] { CN: '*.stackexchange.com' },
[...]
valid_from: 'Mar  6 14:17:27 2022 GMT',
valid_to: 'Jun  4 14:17:26 2022 GMT',
[...]
  • Related