- 
                Notifications
    
You must be signed in to change notification settings  - Fork 2.9k
 
fix: improve URL parsing error handling in ListInputProvider #6448
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
base: dev
Are you sure you want to change the base?
Conversation
- Add *types.Options field to ListInputProvider struct - Initialize options field in New() constructor - Enhance URL parsing error handling: - Change from debug messages to error messages - Distinguish single-target (-u) and batch (-l) modes - Single-target mode: exit immediately with os.Exit(1) - Batch mode: log error and skip invalid target - Apply consistent logic to both Set and Del functions Fixes projectdiscovery#6416
          
WalkthroughAdds options to ListInputProvider, refactors error handling in Set/Del to branch on single-target vs batch mode, switches fmt errors to structured logging, adjusts deletion to use original input for IPs, and exits on invalid single-target inputs while skipping in batch mode. Changes
 Sequence Diagram(s)sequenceDiagram
  autonumber
  participant User
  participant ListInputProvider as ListInputProvider
  participant Options as Options
  participant Logger as Logger
  participant OS as OS
  User->>ListInputProvider: Set(value)
  ListInputProvider->>ListInputProvider: parse URL / validate hostname
  alt invalid target
    ListInputProvider->>Options: check TargetsFilePath / Targets
    alt Single-target mode
      ListInputProvider->>Logger: info("invalid target ...")
      ListInputProvider->>OS: Exit(1)
    else Batch mode
      ListInputProvider->>Logger: warn("skipping invalid target ...")
      ListInputProvider-->>User: return (skip)
    end
  else valid target
    ListInputProvider-->>User: proceed (add)
  end
    sequenceDiagram
  autonumber
  participant User
  participant ListInputProvider as ListInputProvider
  participant Options as Options
  participant Logger as Logger
  participant OS as OS
  User->>ListInputProvider: Del(value)
  ListInputProvider->>ListInputProvider: parse (URL/IP)
  alt invalid target
    ListInputProvider->>Options: check TargetsFilePath / Targets
    alt Single-target mode
      ListInputProvider->>Logger: info("invalid target ...")
      ListInputProvider->>OS: Exit(1)
    else Batch mode
      ListInputProvider->>Logger: warn("skipping invalid target ...")
      ListInputProvider-->>User: return (skip)
    end
  else IP deletion
    ListInputProvider->>ListInputProvider: metaInput.Input = value
    ListInputProvider-->>User: proceed (delete)
  else URL deletion
    ListInputProvider-->>User: proceed (delete)
  end
    Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Assessment against linked issues
 Assessment against linked issues: Out-of-scope changes
 Possibly related PRs
 Poem
 ✨ Finishing Touches
 🧪 Generate unit tests
 Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit: 
 SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type  Other keywords and placeholders
 CodeRabbit Configuration File (
 | 
    
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.
Actionable comments posted: 2
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️  Outside diff range comments (1)
pkg/input/provider/list/hmap.go (1)
448-451: Use the trimmed URL when setting metaInput.Input (consistency bug).Using value (untrimmed) can change the delItem key/parse behavior vs Set which uses URL (trimmed). This can make exclusions fail to match.
- metaInput := contextargs.NewMetaInput() - metaInput.Input = value + metaInput := contextargs.NewMetaInput() + metaInput.Input = URL metaInput.CustomIP = ip i.delItem(metaInput)
🧹 Nitpick comments (3)
pkg/input/provider/list/hmap.go (3)
41-41: Storing global options on the provider — add a clear contract (and guard nil).Keeping a pointer to types.Options here is fine, but please document immutability expectations and add a nil-guard in New to avoid panics if someone constructs Options with a nil .Options.
Example guard near New(...):
if opts == nil || opts.Options == nil { return nil, errors.New("list input provider: options must be non-nil") }
74-74: Initialize options with an early nil-check.New dereferences multiple fields on options later; protect against nil to fail fast with a helpful error.
if options == nil { return nil, errors.New("list input provider: options must be non-nil") }
538-539: Regex errors ignored; untrusted patterns can backfire.regexp.MatchString(metaInput.Input, tmpUrl.Host) ignores compile errors and may ReDoS. Compile once, handle error, and pre-validate exclude patterns.
- matched, _ := regexp.MatchString(metaInput.Input, tmpUrl.Host) + re, reErr := regexp.Compile(metaInput.Input) + if reErr != nil { + gologger.Warning().Msgf("invalid exclude regex %q: %v", metaInput.Input, reErr) + return nil + } + matched := re.MatchString(tmpUrl.Host)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
 - Jira integration is disabled by default for public repositories
 - Linear integration is disabled by default for public repositories
 
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
pkg/input/provider/list/hmap.go(4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
pkg/input/provider/list/hmap.go (1)
pkg/types/types.go (1)
Options(32-464)
🔇 Additional comments (1)
pkg/input/provider/list/hmap.go (1)
62-109: Clarify timeout error suppression vs parse-time exits
- This change only suppresses parse-time invalid-target logs (os.Exit in pkg/input/provider/list/hmap.go at lines 159–161 and 409–413).
 - It does not address the repeated network-layer timeout errors for unresponsive hosts (issue #6416); I found no gologger logs for connection timeouts in pkg—please verify where timeouts are handled/retried and adjust logging accordingly.
 
| if err != nil { | ||
| gologger.Error().Msgf("Failed to parse URL %v: %v", URL, err) | ||
| } else { | ||
| gologger.Error().Msgf("Invalid hostname for URL %v", URL) | ||
| } | ||
| 
               | 
          ||
| // Check if this is single target mode (-u) or batch mode (-l) | ||
| if i.options.TargetsFilePath == "" && len(i.options.Targets) <= 1 { | ||
| // Single target mode: exit immediately | ||
| gologger.Info().Msg("Stopping scan due to invalid target") | ||
| os.Exit(1) | ||
| } else { | ||
| // Batch mode: log error and skip this target | ||
| gologger.Warning().Msgf("Skipping invalid target: %v", URL) | ||
| return | ||
| } | 
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.
🛠️ Refactor suggestion
Invalid-target handling: wrong single-target detection, duplicate logs, and os.Exit in library code.
- Misclassification: stdin/uncover-only runs (Targets==0, TargetsFilePath=="") are treated as “single-target”, causing premature exit on any bad line.
 - Duplicate logs: you emit an Error then an Info/Warning for the same invalid input.
 - os.Exit here makes the package kill the process; better keep exit decisions at the CLI/runner layer.
 
Minimum fix: correct detection and emit a single message; keep exit only if you must. Suggested patch:
-		if err != nil {
-			gologger.Error().Msgf("Failed to parse URL %v: %v", URL, err)
-		} else {
-			gologger.Error().Msgf("Invalid hostname for URL %v", URL)
-		}
-		
-		// Check if this is single target mode (-u) or batch mode (-l)
-		if i.options.TargetsFilePath == "" && len(i.options.Targets) <= 1 {
-			// Single target mode: exit immediately
-			gologger.Info().Msg("Stopping scan due to invalid target")
-			os.Exit(1)
-		} else {
-			// Batch mode: log error and skip this target
-			gologger.Warning().Msgf("Skipping invalid target: %v", URL)
-			return
-		}
+		// Single clear message + correct single/batch detection
+		reason := "empty hostname"
+		if err != nil {
+			reason = err.Error()
+		}
+		if i.isSingleTargetMode() {
+			gologger.Error().Msgf("Invalid target %v: %v", URL, reason)
+			// Ideally propagate to caller instead of exiting here.
+			os.Exit(1)
+		} else {
+			gologger.Warning().Msgf("Skipping invalid target %v: %v", URL, reason)
+			return
+		}Add this helper once in the file:
func (i *ListInputProvider) isSingleTargetMode() bool {
	if i == nil || i.options == nil {
		return false
	}
	// Consider only explicit -u usage; stdin/-l/uncover are batch-like.
	return i.options.TargetsFilePath == "" &&
		!i.options.Stdin &&
		!i.options.Uncover &&
		len(i.options.Targets) == 1
}If feasible, prefer bubbling an error to the caller instead of os.Exit to keep package-level code side-effect free. I can draft that refactor if you want.
🤖 Prompt for AI Agents
In pkg/input/provider/list/hmap.go around lines 151 to 166: the current logic
misdetects single-target mode (treats stdin/uncover runs as single-target),
emits duplicate logs for the same invalid URL, and calls os.Exit from library
code; fix by adding a helper method isSingleTargetMode on ListInputProvider that
returns true only when TargetsFilePath=="" AND Targets length == 1 AND explicit
flags Stdin and Uncover are false (also guard i/options nil), replace the
current detection with that helper, remove the redundant Error+Info/Warning pair
so only one log entry is emitted for an invalid target, and do NOT call os.Exit
here — instead return an error or a sentinel so the CLI/runner layer can decide
to exit; if you prefer, change the function signature to return an error so
callers can handle exit behavior.
| if err != nil { | ||
| gologger.Error().Msgf("Failed to parse URL %v: %v", URL, err) | ||
| } else { | ||
| gologger.Error().Msgf("Invalid hostname for URL %v", URL) | ||
| } | ||
| 
               | 
          ||
| // Check if this is single target mode (-u) or batch mode (-l) | ||
| if i.options.TargetsFilePath == "" && len(i.options.Targets) <= 1 { | ||
| // Single target mode: exit immediately | ||
| gologger.Info().Msg("Stopping scan due to invalid target") | ||
| os.Exit(1) | ||
| } else { | ||
| // Batch mode: log error and skip this target | ||
| gologger.Warning().Msgf("Skipping invalid target: %v", URL) | ||
| return | ||
| } | 
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.
🛠️ Refactor suggestion
Don’t os.Exit from Del; treat invalid excludes as non-fatal and skip.
Exiting from Del can kill a scan due to an invalid exclude pattern even in -l/stdin runs. Keep it a single warning and continue.
-		if err != nil {
-			gologger.Error().Msgf("Failed to parse URL %v: %v", URL, err)
-		} else {
-			gologger.Error().Msgf("Invalid hostname for URL %v", URL)
-		}
-		
-		// Check if this is single target mode (-u) or batch mode (-l)
-		if i.options.TargetsFilePath == "" && len(i.options.Targets) <= 1 {
-			// Single target mode: exit immediately
-			gologger.Info().Msg("Stopping scan due to invalid target")
-			os.Exit(1)
-		} else {
-			// Batch mode: log error and skip this target
-			gologger.Warning().Msgf("Skipping invalid target: %v", URL)
-			return
-		}
+		reason := "empty hostname"
+		if err != nil {
+			reason = err.Error()
+		}
+		gologger.Warning().Msgf("Skipping invalid exclude target %v: %v", URL, reason)
+		return📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if err != nil { | |
| gologger.Error().Msgf("Failed to parse URL %v: %v", URL, err) | |
| } else { | |
| gologger.Error().Msgf("Invalid hostname for URL %v", URL) | |
| } | |
| // Check if this is single target mode (-u) or batch mode (-l) | |
| if i.options.TargetsFilePath == "" && len(i.options.Targets) <= 1 { | |
| // Single target mode: exit immediately | |
| gologger.Info().Msg("Stopping scan due to invalid target") | |
| os.Exit(1) | |
| } else { | |
| // Batch mode: log error and skip this target | |
| gologger.Warning().Msgf("Skipping invalid target: %v", URL) | |
| return | |
| } | |
| // Treat invalid exclude patterns as non-fatal—just warn and skip | |
| reason := "empty hostname" | |
| if err != nil { | |
| reason = err.Error() | |
| } | |
| gologger.Warning().Msgf("Skipping invalid exclude target %v: %v", URL, reason) | |
| return | 
🤖 Prompt for AI Agents
In pkg/input/provider/list/hmap.go around lines 401 to 416, the code currently
calls os.Exit(1) when encountering an invalid target, which terminates the
entire scan; instead, treat invalid excludes/non-fatal parse failures as
non-fatal: remove the os.Exit call, change the logic so that both single-target
and batch runs log an appropriate warning or info and return to skip processing
this target (for single-target mode, return an error to the caller or set a
non-fatal status rather than exiting), ensuring the function does not terminate
the process and batch/stdin runs continue.
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.
Just a quick note: this case is kind of similar on the surface, but the behavior we’re chasing here is different from the linked issue.
Unresolved questions/TODOs:
- How's the behavior if the target is successfully resolved (valid hostname/IP address)? -- this is the primary case for #6416.
 - Can you verify that this also works with the SDK? -- integration test may be needed.
 
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.
- failing tests
 
Proposed changes
Fixes #6416
Fixes issue where:
Screenshot
Batch mode (-l option)
Single target mode (-u option)
Checklist
Summary by CodeRabbit