// Package scope filters which captured traffic gets recorded to // history - a target scope, in Burp's sense: out-of-scope requests // still proxy through completely normally (nothing is blocked), they // just aren't stored, so unrelated CDN/analytics/tracker noise doesn't // pollute history and search on a real engagement. Deliberately not an // access-control mechanism; that would be a materially different, // riskier feature (breaking a workflow by silently blocking traffic is // a much worse failure mode than a noisier history). package scope import ( "regexp" "strings" ) // Rule is one scope entry. A non-regex Pattern matches by substring // containment against the host (case-insensitive) - "example.com" // matches "example.com", "www.example.com", and "api.example.com" // alike, covering the common "this domain and its subdomains" case // without inventing a separate wildcard syntax. IsRegex switches to a // full regex match against the host, mirroring the same toggle // match-and-replace rules already use, for the same reason: one // consistent mental model across both rule types in this tool. type Rule struct { ID int64 `json:"id"` Enabled bool `json:"enabled"` Pattern string `json:"pattern"` IsRegex bool `json:"is_regex"` } // InScope reports whether host should be recorded, given rules. // An empty rule set (or one with nothing enabled) means "no scope // configured" - everything is in scope, matching this tool's behavior // before scope existed at all, so a fresh install or a user who never // opens the scope view keeps recording everything, not silently // nothing. Once at least one rule is enabled, only a host matching one // of them is in scope. func InScope(rules []Rule, host string) bool { anyEnabled := false for _, r := range rules { if !r.Enabled { continue } anyEnabled = true if ruleMatches(r, host) { return true } } return !anyEnabled } func ruleMatches(r Rule, host string) bool { if r.IsRegex { re, err := regexp.Compile(r.Pattern) if err != nil { return false } return re.MatchString(host) } return strings.Contains(strings.ToLower(host), strings.ToLower(r.Pattern)) }