Skip to content

fix: improve URL parsing error handling in ListInputProvider#6448

Closed
oleveloper wants to merge 3 commits intoprojectdiscovery:devfrom
oleveloper:dev
Closed

fix: improve URL parsing error handling in ListInputProvider#6448
oleveloper wants to merge 3 commits intoprojectdiscovery:devfrom
oleveloper:dev

Conversation

@oleveloper
Copy link
Copy Markdown

@oleveloper oleveloper commented Sep 1, 2025

Proposed changes

  • 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 #6416

Fixes issue where:

  • Single-target mode with invalid hostname now exits immediately
  • Batch mode skips invalid hosts while continuing with valid ones
  • Duplicate error messages replaced with a single clear error message

Screenshot

  • Batch mode (-l option)

    • 스크린샷 2025-09-01 오후 6 37 50
  • Single target mode (-u option)

    • 스크린샷 2025-09-01 오후 6 37 07

Checklist

  • Pull request is created against the dev branch
  • All checks passed (lint, unit/integration/regression tests etc.) with my changes
  • I have added tests that prove my fix is effective or that my feature works
  • I have added necessary documentation (if appropriate)

Summary by CodeRabbit

  • Bug Fixes
    • Improved handling of invalid targets: single-target runs now show a clear message and exit; batch runs log a warning and skip invalid entries without stopping.
    • Enhanced deletion behavior when removing by IP to more reliably match the original input.
    • Switched to structured logging for URL/hostname validation errors, providing clearer diagnostics.

- 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
@auto-assign auto-assign Bot requested a review from dogancanbakir September 1, 2025 09:45
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Sep 1, 2025

Walkthrough

Adds 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

Cohort / File(s) Summary
Input provider: options and control-flow
pkg/input/provider/list/hmap.go
- Added options *types.Options to ListInputProvider and wired via New(...)
- Replaced fmt errors with gologger logging in Set/Del
- Single-target vs batch behavior based on options.TargetsFilePath and options.Targets
- Single-target: log and os.Exit(1) on invalid target; Batch: warn and skip
- In Del, assign metaInput.Input = value for IP deletions
- Removed unused fmt import

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
Loading
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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Reduce extra verbose logging on unresponsive hosts; ensure only one error log (#6416) Changes focus on invalid target parsing/hostname; unresponsive host behavior not shown here.

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Add options *types.Options to ListInputProvider and wire through constructor (pkg/input/provider/list/hmap.go) Expands provider state unrelated to controlling verbose logs for unresponsive hosts.
Introduce os.Exit(1) on invalid single-target inputs (pkg/input/provider/list/hmap.go) Alters process termination behavior, not specified in the logging bug objective.
Change Del to use metaInput.Input = value for IP deletions (pkg/input/provider/list/hmap.go) Adjusts deletion semantics; not tied to reducing verbose logs on unresponsive hosts.

Possibly related PRs

Poem

I hop through lists with careful cheer,
One target? I’ll halt—batch mode? I steer.
Logs now whisper, not a storm,
Invalid crumbs, I don’t perform.
With options tucked beneath my ear,
I prune and set—precise and clear. 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a 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.

📥 Commits

Reviewing files that changed from the base of the PR and between 48c389b and 7b2094d.

📒 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.

Comment on lines +151 to +166
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
}
Copy link
Copy Markdown
Contributor

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.

Comment on lines +401 to +416
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
}
Copy link
Copy Markdown
Contributor

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.

Suggested change
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.

Copy link
Copy Markdown
Member

@dwisiswant0 dwisiswant0 left a 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.

@Mzack9999 Mzack9999 self-requested a review September 15, 2025 13:06
Copy link
Copy Markdown
Member

@Mzack9999 Mzack9999 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • failing tests

@github-actions
Copy link
Copy Markdown

This pull request has been automatically marked as stale due to inactivity. It will be closed in 7 days if no further activity occurs. Please update if you wish to keep it open.

@github-actions github-actions Bot added the Status: Stale This issue/PR has been inactive for a while and may be closed soon if no further activity occ label Apr 19, 2026
@github-actions
Copy link
Copy Markdown

This pull request has been automatically closed due to inactivity. If you think this is a mistake or would like to continue working on it, please comment or feel free to reopen it.

@github-actions github-actions Bot added the Status: Abandoned This issue is no longer important to the requestor and no one else has shown an interest in it. label Apr 26, 2026
@github-actions github-actions Bot closed this Apr 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Status: Abandoned This issue is no longer important to the requestor and no one else has shown an interest in it. Status: Stale This issue/PR has been inactive for a while and may be closed soon if no further activity occ

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Fix extra logging when running in verbose mode on unresponsive hosts

3 participants