From a6faae704ba3ec5da9a2097f871fdd32f4961852 Mon Sep 17 00:00:00 2001 From: lakshit verma Date: Mon, 24 Aug 2026 00:43:33 +0530 Subject: [PATCH] rfc6962: normalize precert SANs through dedupeLower The x509 path lowercased names, trimmed trailing dots and wildcard prefixes, dropped control bytes, and deduplicated; the precert (TBS) path returned raw SAN strings with none of that, leaving the ingest filter single-layered for precerts and inconsistent casing in stored names. Route both paths through the same normalization; test covers mixed case, trailing dot, wildcard, and duplicate collapse. --- internal/rfc6962/leaf.go | 4 +++- internal/rfc6962/leaf_test.go | 18 ++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/internal/rfc6962/leaf.go b/internal/rfc6962/leaf.go index 911fd18..854c91c 100644 --- a/internal/rfc6962/leaf.go +++ b/internal/rfc6962/leaf.go @@ -57,7 +57,9 @@ func DecodeLeafEntry(e LeafEntry) (*DecodedLeaf, error) { if err != nil { return nil, err } - out.Names = names + // Same normalization as the x509 path: lowercase, strip trailing + // dots and wildcard prefixes, reject control bytes, dedupe. + out.Names = dedupeLower(names) out.SCTStamps = scts default: return nil, fmt.Errorf("unknown entry type %d", te.EntryType) diff --git a/internal/rfc6962/leaf_test.go b/internal/rfc6962/leaf_test.go index 472fe18..5dcca91 100644 --- a/internal/rfc6962/leaf_test.go +++ b/internal/rfc6962/leaf_test.go @@ -175,3 +175,21 @@ func TestControlBytesRejected(t *testing.T) { t.Errorf("names = %q, want [ok.example.com]", leaf.Names) } } + +func TestPrecertNamesNormalized(t *testing.T) { + cert := makeCert(t, []string{"Mixed.Case.Example.COM", "mixed.case.example.com.", "*.Wild.Example.com"}) + signed := append(append(make([]byte, 32), uint24(len(cert.RawTBSCertificate))...), cert.RawTBSCertificate...) + leaf, err := DecodeLeafEntry(LeafEntry{LeafInput: buildLeaf(1, signed, 42)}) + if err != nil { + t.Fatal(err) + } + want := []string{"mixed.case.example.com", "wild.example.com"} + if len(leaf.Names) != len(want) { + t.Fatalf("names = %v; want %v", leaf.Names, want) + } + for i := range want { + if leaf.Names[i] != want[i] { + t.Fatalf("names[%d] = %q; want %q", i, leaf.Names[i], want[i]) + } + } +}