Match cookie-database denylist on domain forms

The cookie-database aggregator backstop normalised the agent's
third-party name and looked it up against bare brand keys, but
normalizeAlnum folds the eTLD into the key (cookiedatabase.org ->
cookiedatabaseorg). Domain- and URL-form attributions therefore
slipped past the exact lookup, letting noisy aggregator names be
accepted instead of discarded.

Add uri.DomainLabel to reduce a host-like string to its primary
registrable label and check it alongside the normalised name, so
both brand ("Cookiepedia") and domain forms ("cookiedatabase.org",
"https://www.cookiepedia.co.uk/list") resolve to the same key.

Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
Émile Ré
2026-06-10 09:41:31 +02:00
parent a68c2ef108
commit ae61c20791
4 changed files with 80 additions and 5 deletions

View File

@@ -103,6 +103,35 @@ func ExtractDomain(rawURL string) string {
return domain
}
// DomainLabel extracts the primary registrable label from a host-like
// string. It accepts bare hostnames, full URLs, and host:port forms:
//
// "cookiedatabase.org" → "cookiedatabase"
// "https://www.cookiedatabase.org/list" → "cookiedatabase"
// "Cookiepedia" → "" (no public suffix)
//
// Returns an empty string when the input carries no registrable domain
// (e.g. a bare brand name or an unparseable value).
func DomainLabel(raw string) string {
host := strings.ToLower(strings.TrimSpace(raw))
if i := strings.Index(host, "://"); i != -1 {
host = host[i+len("://"):]
}
host, _, _ = strings.Cut(host, "/")
host, _, _ = strings.Cut(host, "?")
host, _, _ = strings.Cut(host, ":")
domain, err := publicsuffix.EffectiveTLDPlusOne(host)
if err != nil {
return ""
}
label, _, _ := strings.Cut(domain, ".")
return label
}
// FilterFirstPartyDomains removes domains that match the eTLD+1 of
// siteOrigin. Tracker scripts loaded through a first-party proxy (e.g.
// t.probo.com proxying PostHog on a probo.com site) share the site's

View File

@@ -292,6 +292,37 @@ func TestExtractDomain(t *testing.T) {
}
}
func TestDomainLabel(t *testing.T) {
t.Parallel()
tests := []struct {
name string
raw string
want string
}{
{"bare domain", "cookiedatabase.org", "cookiedatabase"},
{"domain with www", "www.cookiedatabase.org", "cookiedatabase"},
{"full url", "https://www.cookiedatabase.org/list", "cookiedatabase"},
{"url with query", "https://cookifi.com/?ref=x", "cookifi"},
{"host with port", "cookieserve.com:8443", "cookieserve"},
{"co.uk tld", "https://www.cookiepedia.co.uk/list", "cookiepedia"},
{"uppercase", "CookieDatabase.ORG", "cookiedatabase"},
{"surrounding spaces", " cookifi.com ", "cookifi"},
{"bare brand no suffix", "Cookiepedia", ""},
{"empty string", "", ""},
}
for _, tt := range tests {
t.Run(
tt.name,
func(t *testing.T) {
t.Parallel()
assert.Equal(t, tt.want, DomainLabel(tt.raw))
},
)
}
}
func TestFilterFirstPartyDomains(t *testing.T) {
t.Parallel()