diff --git a/internal/imgcache/whitelist.go b/internal/imgcache/whitelist.go index df24be2..5baf101 100644 --- a/internal/imgcache/whitelist.go +++ b/internal/imgcache/whitelist.go @@ -6,22 +6,19 @@ import ( ) // HostWhitelist implements the Whitelist interface for checking allowed source hosts. +// Only exact host matches are supported. Leading dots in patterns are stripped +// (e.g. ".example.com" becomes an exact match for "example.com"). type HostWhitelist struct { - // exactHosts contains hosts that must match exactly (e.g., "cdn.example.com") - exactHosts map[string]struct{} - // suffixHosts contains domain suffixes to match (e.g., ".example.com" matches "cdn.example.com") - suffixHosts []string + // hosts contains hosts that must match exactly (e.g., "cdn.example.com") + hosts map[string]struct{} } // NewHostWhitelist creates a whitelist from a list of host patterns. -// Patterns starting with "." are treated as suffix matches. -// Examples: -// - "cdn.example.com" - exact match only -// - ".example.com" - matches cdn.example.com, images.example.com, etc. +// All patterns are treated as exact matches. Leading dots are stripped +// for backwards compatibility (e.g. ".example.com" matches "example.com" only). func NewHostWhitelist(patterns []string) *HostWhitelist { w := &HostWhitelist{ - exactHosts: make(map[string]struct{}), - suffixHosts: make([]string, 0), + hosts: make(map[string]struct{}), } for _, pattern := range patterns { @@ -30,17 +27,22 @@ func NewHostWhitelist(patterns []string) *HostWhitelist { continue } - if strings.HasPrefix(pattern, ".") { - w.suffixHosts = append(w.suffixHosts, pattern) - } else { - w.exactHosts[pattern] = struct{}{} + // Strip leading dot — suffix matching is not supported. + // ".example.com" is treated as exact match for "example.com". + pattern = strings.TrimPrefix(pattern, ".") + + if pattern == "" { + continue } + + w.hosts[pattern] = struct{}{} } return w } // IsWhitelisted checks if a URL's host is in the whitelist. +// Only exact host matches are supported. func (w *HostWhitelist) IsWhitelisted(u *url.URL) bool { if u == nil { return false @@ -51,32 +53,17 @@ func (w *HostWhitelist) IsWhitelisted(u *url.URL) bool { return false } - // Check exact match - if _, ok := w.exactHosts[host]; ok { - return true - } + _, ok := w.hosts[host] - // Check suffix match - for _, suffix := range w.suffixHosts { - if strings.HasSuffix(host, suffix) { - return true - } - // Also match if host equals the suffix without the leading dot - // e.g., pattern ".example.com" should match "example.com" - if host == strings.TrimPrefix(suffix, ".") { - return true - } - } - - return false + return ok } // IsEmpty returns true if the whitelist has no entries. func (w *HostWhitelist) IsEmpty() bool { - return len(w.exactHosts) == 0 && len(w.suffixHosts) == 0 + return len(w.hosts) == 0 } // Count returns the total number of whitelist entries. func (w *HostWhitelist) Count() int { - return len(w.exactHosts) + len(w.suffixHosts) + return len(w.hosts) }