From d6decf2f177567fba5bbc6ff520887626f5a5371 Mon Sep 17 00:00:00 2001
From: Paraspandey-debugs
Date: Thu, 25 Jun 2026 16:56:10 +0530
Subject: [PATCH] tls: fix IPv6 hostname verification regression
The previous normalization logic applied domainToASCII() to all hostnames,
which returns an empty string for raw IPv6 addresses. This caused the IP SAN
check to be skipped and verification to incorrectly fall back to domain
matching. This patch moves the IP address check before any IDNA conversion,
ensuring IPv6 (and IPv4) addresses are compared directly against the
certificate's IP Subject Alternative Names.
Adds regression tests for IPv6 SAN verification.
Fixes: https://github.com/nodejs/node/issues/64032
Signed-off-by: Paraspandey-debugs
---
lib/tls.js | 6 +++---
.../test-tls-check-server-identity.js | 21 +++++++++++++++++++
2 files changed, 24 insertions(+), 3 deletions(-)
diff --git a/lib/tls.js b/lib/tls.js
index 283e5f5bc7870a..97af5dde408e72 100644
--- a/lib/tls.js
+++ b/lib/tls.js
@@ -336,7 +336,7 @@ function check(hostParts, pattern, wildcards) {
// RFC 6125 does not allow wildcard substitution for components
// containing IDNA A-labels (Punycode) so match those verbatim.
if (patternSubdomainParts.length === 1 ||
- patternSubdomain.includes('xn--'))
+ patternSubdomain.includes('xn--'))
return hostSubdomain === patternSubdomain;
if (!wildcards)
@@ -409,11 +409,11 @@ exports.checkServerIdentity = function checkServerIdentity(hostname, cert) {
const ips = [];
hostname = '' + hostname;
- const hostnameASCII = domainToASCII(hostname);
// Remove trailing dots for error messages and matching.
hostname = unfqdn(hostname);
- const hostnameASCIIWithoutFQDN = unfqdn(hostnameASCII);
+ const hostnameASCIIWithoutFQDN = net.isIP(hostname) ?
+ hostname : domainToASCII(hostname);
if (altNames) {
const splitAltNames = altNames.includes('"') ?
diff --git a/test/parallel/test-tls-check-server-identity.js b/test/parallel/test-tls-check-server-identity.js
index 4863fca55165ee..e4ff950a61c2de 100644
--- a/test/parallel/test-tls-check-server-identity.js
+++ b/test/parallel/test-tls-check-server-identity.js
@@ -404,6 +404,27 @@ const tests = [
error: 'Host: xn--bcher-kva.example.com. is not cert\'s CN: ' +
'xn--*.example.com',
},
+ // IPv6 addresses
+ {
+ host: '::1', cert: {
+ subjectaltname: 'IP Address:0:0:0:0:0:0:0:1',
+ subject: {}
+ }
+ },
+ {
+ host: '::1', cert: {
+ subjectaltname: 'IP Address:127.0.0.1',
+ subject: {}
+ },
+ error: 'IP: ::1 is not in the cert\'s list: ' +
+ '127.0.0.1'
+ },
+ {
+ host: '2001:db8::1', cert: {
+ subjectaltname: 'IP Address:2001:0DB8:0000:0000:0000:0000:0000:0001',
+ subject: {}
+ }
+ },
];
tests.forEach(function(test, i) {