fix: don't report DNSSEC as enabled for unsigned WHOIS records

The check /signed|yes|true/ matched "unsigned", so every unsigned domain looked
signed over WHOIS (google.com, wikipedia.org, nic.xyz, ...) while RDAP said
otherwise. Require the value to start with signed/yes/true/active, read .rs's
"DNSSEC signed" key, and accept any of several values (.kr repeats the field in
Korean).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
jakeandClaude Opus 5.5 committed 2026-10-03 15:05:11 -04:00
1 parent fd8a63962d
commit 54f4dcbc64
2 files changed
+25 -2

No files matched your search

+19
View File
@@ -397,3 +397,22 @@ test("WHOIS 'Reseller Name' (.au, .th) sets reseller", () => {
.reseller,
).toBeUndefined();
});
test.each([
["DNSSEC: unsigned", false],
["DNSSEC: Inactive", false], // .ro
["DNSSEC: signedDelegation", true],
["dnssec: signed delegation", true], // .se
["DNSSEC: active", true], // .bg
["DNSSEC: yes", true],
["DNSSEC signed: yes", true], // .rs
["DNSSEC : 서명\nDNSSEC : signed", true], // .kr
])("WHOIS DNSSEC %j -> enabled %s", (line, enabled) => {
const rec = normalizeWhois(
"example.test",
"test",
`Domain Name: example.test\n${line}\n`,
undefined,
);
expect(rec.dnssec?.enabled).toBe(enabled);
});
+6 -2
View File
@@ -237,8 +237,12 @@ export function normalizeWhois(
const registrant = contacts?.find((c) => c.type === "registrant");
const privacyEnabled = isPrivacyContact(registrant);
const dnssecRaw = (map.dnssec?.[0] || "").toLowerCase();
const dnssec = dnssecRaw ? { enabled: /signed|yes|true/.test(dnssecRaw) } : undefined;
// "signedDelegation", "Signed delegation", "yes", "active" (.bg, .md); not "unsigned" or
// "Inactive". .kr repeats the field in Korean, so any value may carry the answer.
const dnssecValues = [...(map.dnssec ?? []), ...(map["dnssec signed"] ?? [])]; // .rs
const dnssec = dnssecValues.length
? { enabled: dnssecValues.some((v) => /^(?:signed|yes|true|active)/i.test(v.trim())) }
: undefined;
// Simple lock derivation from statuses
const transferLock = !!statuses?.some((s) =>