From c28ca6527ea94c3c521739ea6446a01b88d5d37a Mon Sep 17 00:00:00 2001 From: alfredo-family Date: Sat, 14 Mar 2026 18:35:47 +0100 Subject: [PATCH 1/3] fix: handle comma-separated entries in -l/-list and stdin input Split comma-separated targets when reading from -l file or stdin, matching the existing -u flag behavior that uses CommaSeparatedStringSliceOptions. Fixes #859 --- internal/runner/runner.go | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index 91e80136..a157e05d 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -439,8 +439,11 @@ func (r *Runner) normalizeAndQueueInputs(inputs chan taskInput) error { scanner := bufio.NewScanner(file) for scanner.Scan() { text := scanner.Text() - if text != "" { - r.processInputItem(text, inputs) + for _, item := range strings.Split(text, ",") { + item = strings.TrimSpace(item) + if item != "" { + r.processInputItem(item, inputs) + } } } } @@ -448,8 +451,11 @@ func (r *Runner) normalizeAndQueueInputs(inputs chan taskInput) error { scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { text := scanner.Text() - if text != "" { - r.processInputItem(text, inputs) + for _, item := range strings.Split(text, ",") { + item = strings.TrimSpace(item) + if item != "" { + r.processInputItem(item, inputs) + } } } } From c135e77cb00cae96e6a8c204b847a493fe9d6c5a Mon Sep 17 00:00:00 2001 From: alfredo-family Date: Sat, 14 Mar 2026 18:55:20 +0100 Subject: [PATCH 2/3] fix: add scanner.Err() checks after file and stdin scanner loops Address CodeRabbit review: check scanner.Err() after both scanner loops to surface token-size or I/O errors instead of silently dropping targets. --- internal/runner/runner.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/internal/runner/runner.go b/internal/runner/runner.go index a157e05d..c9d350ef 100644 --- a/internal/runner/runner.go +++ b/internal/runner/runner.go @@ -446,6 +446,9 @@ func (r *Runner) normalizeAndQueueInputs(inputs chan taskInput) error { } } } + if err := scanner.Err(); err != nil { + return errkit.Wrap(err, "could not read input file") + } } if r.hasStdin { scanner := bufio.NewScanner(os.Stdin) @@ -458,6 +461,9 @@ func (r *Runner) normalizeAndQueueInputs(inputs chan taskInput) error { } } } + if err := scanner.Err(); err != nil { + return errkit.Wrap(err, "could not read stdin input") + } } return nil } From a2c6745c85627d28aea86267a76ca4cac6511922 Mon Sep 17 00:00:00 2001 From: Gengyscan Date: Tue, 17 Mar 2026 19:25:20 +0100 Subject: [PATCH 3/3] test: add regression tests for comma-separated file input Adds 6 table-driven subtests covering: - comma-separated entries (basic split) - spaces around commas (trimming) - single entry passthrough (no comma) - trailing comma filtering (empty entries) - host:port with commas (custom port parsing) - multiple lines with commas (multi-line file) All tests exercise normalizeAndQueueInputs via temp file input. --- internal/runner/runner_test.go | 71 ++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/internal/runner/runner_test.go b/internal/runner/runner_test.go index b4ed856e..5666306f 100644 --- a/internal/runner/runner_test.go +++ b/internal/runner/runner_test.go @@ -380,6 +380,77 @@ func Test_CTLogsModeWithAllProbes(t *testing.T) { } } +func Test_CommaSeparatedFileInput(t *testing.T) { + tests := []struct { + name string + content string + expected []string + }{ + { + name: "comma-separated entries", + content: "scanme.sh,example.com", + expected: []string{"scanme.sh", "example.com"}, + }, + { + name: "comma-separated with spaces", + content: "host1.com , host2.com , host3.com", + expected: []string{"host1.com", "host2.com", "host3.com"}, + }, + { + name: "single entry no comma", + content: "scanme.sh", + expected: []string{"scanme.sh"}, + }, + { + name: "trailing comma filtered", + content: "a.com,b.com,", + expected: []string{"a.com", "b.com"}, + }, + { + name: "host with port", + content: "example.com:8443,scanme.sh:443", + expected: []string{"example.com", "scanme.sh"}, + }, + { + name: "multiple lines with commas", + content: "a.com,b.com\nc.com,d.com", + expected: []string{"a.com", "b.com", "c.com", "d.com"}, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + tmpFile, err := os.CreateTemp("", "tlsx-test-*.txt") + require.NoError(t, err) + defer os.Remove(tmpFile.Name()) + + _, err = tmpFile.WriteString(tc.content) + require.NoError(t, err) + require.NoError(t, tmpFile.Close()) + + options := &clients.Options{ + Ports: []string{"443"}, + InputList: tmpFile.Name(), + } + runner := &Runner{options: options} + + inputs := make(chan taskInput, 100) + errCh := make(chan error, 1) + go func() { + errCh <- runner.normalizeAndQueueInputs(inputs) + close(inputs) + }() + + var hosts []string + for task := range inputs { + hosts = append(hosts, task.host) + } + require.NoError(t, <-errCh) + require.ElementsMatch(t, tc.expected, hosts) + }) + } +} + func Test_CTLogsModeOutputOptions(t *testing.T) { // Test that CT logs mode works with various output options testCases := []struct {