Skip to content

fix(runner): split comma-separated targets from -l file and stdin (#859)#953

Merged
Mzack9999 merged 6 commits intoprojectdiscovery:devfrom
marchantdev:fix/list-comma-separated-targets-859
Mar 19, 2026
Merged

fix(runner): split comma-separated targets from -l file and stdin (#859)#953
Mzack9999 merged 6 commits intoprojectdiscovery:devfrom
marchantdev:fix/list-comma-separated-targets-859

Conversation

@marchantdev
Copy link
Copy Markdown

@marchantdev marchantdev commented Mar 10, 2026

Summary

The -u flag accepts comma-separated hosts natively via goflags.CommaSeparatedStringSliceOptions. The -l file path (and stdin) did not: every raw line was handed directly to processInputItem, so a file containing 192.168.1.0/24,192.168.2.0/24 was treated as a single, invalid host:

[WRN] Could not connect input 192.168.1.0/24,192.168.2.0/24:443
      [auto,ztls:RUNTIME] failed to setup connection
      <- could not dial address <- no address found for host

Fixes #859.

Root cause

normalizeAndQueueInputs reads the file (and stdin) line-by-line and calls processInputItem(text, inputs) on the full raw line. There was no splitting step.

The -u path goes through goflags.CommaSeparatedStringSliceOptions which splits at flag-parse time, so the runner never sees the commas.

Fix

After reading each line from the file / stdin, split on , and trim whitespace before forwarding to processInputItem. This makes the two input methods behave identically.

// Before
r.processInputItem(text, inputs)

// After
for _, item := range strings.Split(text, ",") {
    if item = strings.TrimSpace(item); item != "" {
        r.processInputItem(item, inputs)
    }
}

The same fix is applied to both the file path and the stdin path.

Test

Added Test_CommaSeperatedInputList_normalizeAndQueueInputs which writes a temporary file with a single comma-separated line, runs normalizeAndQueueInputs, and asserts that both hosts are queued individually.

go test ./internal/runner/... -run Test_CommaSeperatedInputList
ok  github.com/projectdiscovery/tlsx/internal/runner 0.129s

Summary by CodeRabbit

  • New Features

    • Accept comma-separated targets on a single line from input files and stdin; each entry is trimmed and queued as an individual target.
  • Tests

    • Added automated test coverage validating splitting and queuing of comma-separated inputs.

/claim #859

The -u flag accepts comma-separated hosts via CommaSeparatedStringSliceOptions,
but the file-based -l (and stdin) path fed each raw line to processInputItem
as a single string. A line like '192.168.1.0/24,192.168.2.0/24' was treated
as one invalid host, producing:

  [WRN] Could not connect input 192.168.1.0/24,192.168.2.0/24:443 ...
        could not dial address <- no address found for host

Fix: when reading lines from the input file or stdin, split each line on
commas and trim whitespace before forwarding to processInputItem, so that
the two input methods behave identically.

A new table-driven unit test verifies that both entries are queued when
the input file contains a comma-separated line.

Fixes #859.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@neo-by-projectdiscovery-dev
Copy link
Copy Markdown

neo-by-projectdiscovery-dev bot commented Mar 10, 2026

Neo - PR Security Review

No security issues found

Highlights

  • Adds comma-separated target parsing for -l file and stdin input to match -u flag behavior
  • Improves file descriptor leak prevention in file writer Close() method
  • Adds regression tests for goroutine leak detection and timeout handling
  • Enhances TLS connection timeout and context handling for better reliability
Hardening Notes
  • Consider rate-limiting file input processing if very large files with thousands of comma-separated targets per line could cause resource exhaustion
  • The CT logs auto-enable feature (banner.go:52-55) activates when no input is provided - ensure documentation clearly explains this default behavior to avoid confusion

Comment @pdneo help for available commands. · Open in Neo

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Mar 10, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 5b8e9473-c1c4-4ab8-bc59-837bb9a33876

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

The runner now splits comma-separated targets on each input line (from files and STDIN), trims whitespace, filters empties, and queues each item individually via a new helper, instead of treating the whole line as one input. Control flow and error handling otherwise unchanged.

Changes

Cohort / File(s) Summary
Input Normalization Enhancement
internal/runner/runner.go
Added processCommaSeparatedTargets(text string, inputs chan taskInput) and updated normalizeAndQueueInputs to split lines by commas, trim entries, filter empties, and call processInputItem for each target.
Test Coverage
internal/runner/runner_test.go
Added Test_CommaSeparatedInputList_normalizeAndQueueInputs to verify comma-separated targets in a single-line input file are split and queued individually.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Poem

🐰 I nibble commas, one by one,
Each host freed to hop and run,
From single line to many more,
Queued and trimmed, I clap—encore! 🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(runner): split comma-separated targets from -l file and stdin (#859)' clearly and specifically describes the main change—enabling comma-separated target parsing in file/stdin inputs, matching the primary objective of the PR.
Linked Issues check ✅ Passed The PR fully addresses issue #859 by implementing comma-separated target splitting in both -l file and stdin input paths, achieving parity with the -u flag behavior and allowing lines like 'prefix1,prefix2,prefix3' to be processed as individual targets.
Out of Scope Changes check ✅ Passed All changes are directly scoped to fixing issue #859: the new processCommaSeparatedTargets helper, updates to normalizeAndQueueInputs, and the test validating comma-separated input splitting. No extraneous modifications detected.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@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: 1

🧹 Nitpick comments (1)
internal/runner/runner.go (1)

443-448: Consider extracting duplicated comma-split logic into a helper.

The same splitting logic appears in both the file and stdin paths. Extracting it improves maintainability.

♻️ Suggested helper extraction
+// processLineWithCommaSeparatedTargets splits a line by comma and queues each non-empty item.
+func (r *Runner) processLineWithCommaSeparatedTargets(text string, inputs chan taskInput) {
+	for _, item := range strings.Split(text, ",") {
+		if item = strings.TrimSpace(item); item != "" {
+			r.processInputItem(item, inputs)
+		}
+	}
+}

Then replace both occurrences:

 		if text != "" {
-			// Support comma-separated targets on a single line, matching the -u flag behaviour.
-			for _, item := range strings.Split(text, ",") {
-				if item = strings.TrimSpace(item); item != "" {
-					r.processInputItem(item, inputs)
-				}
-			}
+			r.processLineWithCommaSeparatedTargets(text, inputs)
 		}

Also applies to: 457-462

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/runner/runner.go` around lines 443 - 448, Duplicate comma-splitting
+ trimming logic should be extracted into a small helper method on the runner
(e.g., r.splitAndProcessInput or r.processCommaSeparatedInputs) that takes the
raw text and the inputs collection, performs strings.Split(text, ","), trims
each item, skips empties, and calls r.processInputItem(item, inputs) for each;
replace both occurrences (the file path handling and the stdin handling) with
calls to this new helper so the behavior is identical and maintenance is
centralized.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/runner/runner_test.go`:
- Around line 433-436: Rename the test function
Test_CommaSeperatedInputList_normalizeAndQueueInputs to
Test_CommaSeparatedInputList_normalizeAndQueueInputs and update the leading
comment text to use "Separated" instead of "Seperated" so both the function name
and its comment read "Separated" (ensure you update every occurrence, including
the test declaration and the comment that begins "//
Test_CommaSeperatedInputList_normalizeAndQueueInputs ...").

---

Nitpick comments:
In `@internal/runner/runner.go`:
- Around line 443-448: Duplicate comma-splitting + trimming logic should be
extracted into a small helper method on the runner (e.g., r.splitAndProcessInput
or r.processCommaSeparatedInputs) that takes the raw text and the inputs
collection, performs strings.Split(text, ","), trims each item, skips empties,
and calls r.processInputItem(item, inputs) for each; replace both occurrences
(the file path handling and the stdin handling) with calls to this new helper so
the behavior is identical and maintenance is centralized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a184f78e-9e53-46d6-bb21-f499b77b6fcb

📥 Commits

Reviewing files that changed from the base of the PR and between d13b67f and 8a6f015.

📒 Files selected for processing (2)
  • internal/runner/runner.go
  • internal/runner/runner_test.go

- Rename Test_CommaSeperatedInputList → Test_CommaSeparatedInputList (typo fix)
- Extract processCommaSeparatedTargets helper to deduplicate comma-split logic
  from file and stdin reading paths
@marchantdev
Copy link
Copy Markdown
Author

Hi @dogancanbakir — this PR adds comma-separated target support to the -l flag, matching the -u flag behavior. Neo security review shows no issues. Would appreciate a review!

@Mzack9999 Mzack9999 changed the base branch from main to dev March 19, 2026 14:27
@marchantdev
Copy link
Copy Markdown
Author

/claim #953

@marchantdev
Copy link
Copy Markdown
Author

/claim #859

1 similar comment
@marchantdev
Copy link
Copy Markdown
Author

/claim #859

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

-l -list option does not understand multiple prefixes, comma-separated in a single line

2 participants