From 81ae0af7e1a6865502ecccbbfa40e0d7c4a6dda8 Mon Sep 17 00:00:00 2001 From: Joseph Adams <105917501+josephadamsdev@users.noreply.github.com> Date: Sat, 17 Jan 2026 13:18:25 +0100 Subject: [PATCH] fix: handle multi-level public suffixes in RDAP lookup (#6752) --- server/model/domain_expiry.js | 19 ++++++++++++------- test/backend-test/test-domain.js | 11 +++++++++++ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/server/model/domain_expiry.js b/server/model/domain_expiry.js index 3502a4b08..6d91b5d63 100644 --- a/server/model/domain_expiry.js +++ b/server/model/domain_expiry.js @@ -30,10 +30,13 @@ async function getRdapServer(tld) { return null; } - for (const service of rdapList["services"]) { - const [tlds, urls] = service; - if (tlds.includes(tld)) { - return urls[0]; + const services = rdapList["services"] ?? []; + const rootTld = tld?.split(".").pop(); + if (rootTld) { + for (const [tlds, urls] of services) { + if (tlds.includes(rootTld)) { + return urls[0]; + } } } log.debug("rdap", `No RDAP server found for TLD ${tld}`); @@ -173,16 +176,18 @@ class DomainExpiry extends BeanModel { }); } - const rdap = await getRdapServer(tld.publicSuffix); + const publicSuffix = tld.publicSuffix; + const rootTld = publicSuffix.split(".").pop(); + const rdap = await getRdapServer(publicSuffix); if (!rdap) { throw new TranslatableError("domain_expiry_unsupported_unsupported_tld_no_rdap_endpoint", { - publicSuffix: tld.publicSuffix, + publicSuffix, }); } return { domain: tld.domain, - tld: tld.publicSuffix, + tld: rootTld, }; } diff --git a/test/backend-test/test-domain.js b/test/backend-test/test-domain.js index c00d94e24..80d448aed 100644 --- a/test/backend-test/test-domain.js +++ b/test/backend-test/test-domain.js @@ -157,6 +157,17 @@ describe("Domain Expiry", () => { assert.strictEqual(supportInfo.tld, "com"); }); + test("supports multi-level public suffix via RDAP fallback (e.g. com.br)", async () => { + const monitor = { + type: "http", + url: "https://record.com.br", + domainExpiryNotification: true, + }; + const supportInfo = await DomainExpiry.checkSupport(monitor); + assert.strictEqual(supportInfo.domain, "record.com.br"); + assert.strictEqual(supportInfo.tld, "br"); + }); + test("handles complex subdomain correctly", async () => { const monitor = { type: "http",