-
-
Notifications
You must be signed in to change notification settings - Fork 509
feat: add --out-of-scope domain filtering option #876
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,6 +12,7 @@ import ( | |
| "time" | ||
|
|
||
| "github.com/briandowns/spinner" | ||
| "github.com/hahwul/dalfox/v2/internal/optimization" | ||
| "github.com/hahwul/dalfox/v2/internal/printing" | ||
| "github.com/hahwul/dalfox/v2/internal/utils" | ||
| model "github.com/hahwul/dalfox/v2/pkg/model" | ||
|
|
@@ -58,6 +59,9 @@ func runPipeCmd(cmd *cobra.Command, args []string) { | |
| targets = append(targets, target) | ||
| } | ||
| targets = voltUtils.UniqueStringSlice(targets) | ||
| if len(options.OutOfScope) > 0 { | ||
| targets = optimization.FilterOutOfScopeTargets(options, targets) | ||
| } | ||
|
Comment on lines
+62
to
+64
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| printing.DalLog("SYSTEM", "Loaded "+strconv.Itoa(len(targets))+" target urls", options) | ||
|
|
||
| multi, _ := cmd.Flags().GetBool("multicast") | ||
|
|
@@ -132,6 +136,10 @@ func runRawDataPipeMode(cmd *cobra.Command) { | |
| target = "https://" + host + path | ||
| } | ||
| } | ||
| if optimization.IsOutOfScope(options, target) { | ||
| printing.DalLog("INFO", "Target is out of scope, skipping", options) | ||
| return | ||
| } | ||
| _, _ = scanning.Scan(target, options, "single") | ||
| } | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,7 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "github.com/hahwul/dalfox/v2/internal/optimization" | ||
| "github.com/hahwul/dalfox/v2/internal/printing" | ||
| "github.com/hahwul/dalfox/v2/pkg/scanning" | ||
| "github.com/spf13/cobra" | ||
|
|
@@ -23,6 +24,10 @@ func runURLCmd(cmd *cobra.Command, args []string) { | |
|
|
||
| printing.Summary(options, args[0]) | ||
| printing.DalLog("SYSTEM", "Using single target mode", options) | ||
| if optimization.IsOutOfScope(options, args[0]) { | ||
| printing.DalLog("INFO", "Target is out of scope, skipping", options) | ||
| return | ||
| } | ||
|
Comment on lines
+27
to
+30
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This out-of-scope check logic is duplicated across multiple command files ( func isTargetOutOfScope(options model.Options, target string) bool {
if optimization.IsOutOfScope(options, target) {
printing.DalLog("INFO", "Target is out of scope, skipping", options)
return true
}
return false
}Then you could simplify this block to: if isTargetOutOfScope(options, args[0]) {
return
} |
||
| if options.Format == "json" { | ||
| printing.DalLog("PRINT", "[", options) | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,67 @@ | ||
| package optimization | ||
|
|
||
| import ( | ||
| "net/url" | ||
| "strings" | ||
|
|
||
| "github.com/hahwul/dalfox/v2/pkg/model" | ||
| ) | ||
|
|
||
| // IsOutOfScope checks if a URL's host matches any out-of-scope pattern. | ||
| // Supports wildcard matching: | ||
| // - "stg.example.com" = exact match only | ||
| // - "*.stg.example.com" = matches subdomains (api.stg.example.com, devapi.stg.example.com) | ||
| func IsOutOfScope(options model.Options, targetURL string) bool { | ||
| if len(options.OutOfScope) == 0 { | ||
| return false | ||
| } | ||
|
|
||
| parsedURL, err := url.Parse(targetURL) | ||
| if err != nil { | ||
| // Treat malformed URLs as out-of-scope for safety | ||
| return true | ||
| } | ||
|
|
||
| host := strings.ToLower(parsedURL.Hostname()) | ||
| // Handle URLs without scheme - url.Parse puts them in Path with empty Host | ||
| if host == "" && parsedURL.Path != "" { | ||
| parsedURL, err = url.Parse("http://" + targetURL) | ||
| if err != nil { | ||
| return true | ||
| } | ||
| host = strings.ToLower(parsedURL.Hostname()) | ||
| } | ||
| for _, pattern := range options.OutOfScope { | ||
| pattern = strings.ToLower(strings.TrimSpace(pattern)) | ||
| if matchDomainPattern(host, pattern) { | ||
| return true | ||
| } | ||
| } | ||
| return false | ||
| } | ||
|
|
||
| // matchDomainPattern checks if host matches the pattern. | ||
| // Pattern "*.example.com" matches "sub.example.com" but not "example.com" | ||
| // Pattern "example.com" matches only "example.com" exactly | ||
| func matchDomainPattern(host, pattern string) bool { | ||
| if strings.HasPrefix(pattern, "*.") { | ||
| suffix := pattern[1:] // ".example.com" | ||
| return strings.HasSuffix(host, suffix) | ||
| } | ||
| return host == pattern | ||
| } | ||
|
|
||
| // FilterOutOfScopeTargets removes out-of-scope URLs from a target list | ||
| func FilterOutOfScopeTargets(options model.Options, targets []string) []string { | ||
| if len(options.OutOfScope) == 0 { | ||
| return targets | ||
| } | ||
|
|
||
| filtered := make([]string, 0, len(targets)) | ||
| for _, target := range targets { | ||
| if !IsOutOfScope(options, target) { | ||
| filtered = append(filtered, target) | ||
| } | ||
| } | ||
| return filtered | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
optimization.FilterOutOfScopeTargetsfunction already checks ifoptions.OutOfScopeis empty and returns early. This outerifcondition is therefore redundant and can be removed to simplify the code.