fix: remove suffix matching from host whitelist
Whitelist entries now support exact host matches only. Leading dots in patterns are stripped for backwards compatibility (.example.com becomes an exact match for example.com). Suffix matching that would match arbitrary subdomains is no longer supported. Closes #27
This commit is contained in:
@@ -6,22 +6,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// HostWhitelist implements the Whitelist interface for checking allowed source hosts.
|
// 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 {
|
type HostWhitelist struct {
|
||||||
// exactHosts contains hosts that must match exactly (e.g., "cdn.example.com")
|
// hosts contains hosts that must match exactly (e.g., "cdn.example.com")
|
||||||
exactHosts map[string]struct{}
|
hosts map[string]struct{}
|
||||||
// suffixHosts contains domain suffixes to match (e.g., ".example.com" matches "cdn.example.com")
|
|
||||||
suffixHosts []string
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewHostWhitelist creates a whitelist from a list of host patterns.
|
// NewHostWhitelist creates a whitelist from a list of host patterns.
|
||||||
// Patterns starting with "." are treated as suffix matches.
|
// All patterns are treated as exact matches. Leading dots are stripped
|
||||||
// Examples:
|
// for backwards compatibility (e.g. ".example.com" matches "example.com" only).
|
||||||
// - "cdn.example.com" - exact match only
|
|
||||||
// - ".example.com" - matches cdn.example.com, images.example.com, etc.
|
|
||||||
func NewHostWhitelist(patterns []string) *HostWhitelist {
|
func NewHostWhitelist(patterns []string) *HostWhitelist {
|
||||||
w := &HostWhitelist{
|
w := &HostWhitelist{
|
||||||
exactHosts: make(map[string]struct{}),
|
hosts: make(map[string]struct{}),
|
||||||
suffixHosts: make([]string, 0),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, pattern := range patterns {
|
for _, pattern := range patterns {
|
||||||
@@ -30,17 +27,22 @@ func NewHostWhitelist(patterns []string) *HostWhitelist {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(pattern, ".") {
|
// Strip leading dot — suffix matching is not supported.
|
||||||
w.suffixHosts = append(w.suffixHosts, pattern)
|
// ".example.com" is treated as exact match for "example.com".
|
||||||
} else {
|
pattern = strings.TrimPrefix(pattern, ".")
|
||||||
w.exactHosts[pattern] = struct{}{}
|
|
||||||
|
if pattern == "" {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w.hosts[pattern] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsWhitelisted checks if a URL's host is in the whitelist.
|
// 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 {
|
func (w *HostWhitelist) IsWhitelisted(u *url.URL) bool {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
return false
|
return false
|
||||||
@@ -51,32 +53,17 @@ func (w *HostWhitelist) IsWhitelisted(u *url.URL) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check exact match
|
_, ok := w.hosts[host]
|
||||||
if _, ok := w.exactHosts[host]; ok {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check suffix match
|
return ok
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsEmpty returns true if the whitelist has no entries.
|
// IsEmpty returns true if the whitelist has no entries.
|
||||||
func (w *HostWhitelist) IsEmpty() bool {
|
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.
|
// Count returns the total number of whitelist entries.
|
||||||
func (w *HostWhitelist) Count() int {
|
func (w *HostWhitelist) Count() int {
|
||||||
return len(w.exactHosts) + len(w.suffixHosts)
|
return len(w.hosts)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user