Skip to content

feat: add csv output support with customizable fields (#745) - #746

Merged
Mzack9999 merged 3 commits into
projectdiscovery:devfrom
ThryLox:feat/csv-output
Jul 2, 2026
Merged

feat: add csv output support with customizable fields (#745)#746
Mzack9999 merged 3 commits into
projectdiscovery:devfrom
ThryLox:feat/csv-output

Conversation

@ThryLox

@ThryLox ThryLox commented Jun 30, 2026

Copy link
Copy Markdown

Summary

Fixes #745. Introduces a new -csv, -c command-line flag to output uncover search results in standard CSV format, integrating seamlessly into existing pipelines (httpx -csv, nuclei -csv).

Key Changes

  1. New Flag: Added -csv / -c flag to options.go to format output as CSV.
  2. Default Field Projection: Defaults to ip,port,host when -csv is used without explicitly overriding the -field flag.
  3. Structured CSV Serialization: Uses Go's native encoding/csv package in the OutputWriter to ensure robust escaping and RFC-4180 compatibility.
  4. Unit Tests: Added unit tests to runner/runner_test.go verifying field parsing, CSV formatting, and duplicate checks.

Summary by CodeRabbit

  • New Features
    • Added --csv (-c) CLI option to enable CSV-formatted output.
    • CSV output includes a single header row per run and projects results using ip, port, and host by default.
  • Bug Fixes
    • Enforces mutual exclusivity between JSON, Raw, and CSV output options.
    • CSV field parsing supports common separators (commas, colons, semicolons, whitespace) and suppresses duplicate rows (dedupe is projection-aware).
  • Tests
    • Added/expanded unit tests for CSV output, delimiter parsing, field mapping, and projection-aware deduplication.

* fix body read err

* feat(agent): add daydaymap search engine support

Add daydaymap as a new supported search engine with complete integration:

- Add daydaymap agent implementation in sources/agent/daydaymap/
- Integrate daydaymap CLI option (-ddm/--daydaymap) in runner options
- Add daydaymap API key configuration in provider and keys
- Register daydaymap in available engines list
- Support DAYDAYMAP_API_KEY environment variable

The implementation follows the existing agent pattern and maintains
consistency with other search engine integrations (greynoise, driftnet, etc).

* adding docs

* fix: thread ctx through sources.Agent (projectdiscovery#724)

---------

Co-authored-by: Doğan Can Bakır <dogancanbakir@protonmail.com>
Co-authored-by: Mzack9999 <mzack9999@protonmail.com>
Co-authored-by: taielab <52345183+taielab@users.noreply.github.com>
Co-authored-by: Dogan Can Bakir <65292895+dogancanbakir@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds a --csv / -c flag for CSV output. CSV mode updates default fields to ip,port,host, writes a header row, and emits results as CSV rows using parsed field lists and result-value mapping.

Changes

CSV Output Support

Layer / File(s) Summary
CSV flag and output field defaults
runner/options.go, README.md
Options gains CSV bool; ParseOptions registers --csv/-c; configureOutput rewrites OutputFields from ip:port to ip,port,host when CSV is enabled, after later parse-stage mutations; docs add the new flag.
CSV writer methods and field helpers
runner/output_writer.go
Adds WriteCSVRow, WriteCSVData, parseFields, and getFieldValues, plus the imports needed for CSV encoding and field splitting.
Runner CSV initialization and result handling
runner/runner.go
Runner.Run parses CSV fields, writes the header row before enumeration, and handles a CSV branch in the result callback.
CSV writer and parseFields tests
runner/runner_test.go
TestOutputWriter_WriteCSVData checks header and row output; TestOutputWriter_WriteCSVData_DistinctProjections, TestGetFieldValues, and TestParseFields extend coverage for deduping, mapping, and delimiter splitting.

Estimated code review effort: 2 (Simple) | ~10 minutes

Poem

🐇 I hop through rows with CSV grace,
A header leads the data race.
-c makes fields march in a line,
ip, port, host — all looking fine.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
Linked Issues check ✅ Passed The PR adds a -c/--csv flag, emits a header row, reuses field projection, defaults to ip,port,host, and includes CSV tests.
Out of Scope Changes check ✅ Passed The changes stay focused on CSV output support, related tests, and README flag docs, with no clear unrelated additions.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding CSV output support with configurable fields.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with 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.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 2

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

20-39: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Strengthen this test to cover escaping and deduplication.

Right now this only proves that a simple row is present somewhere in the buffer. It does not catch regressions in the two CSV-specific contracts added in runner/output_writer.go: RFC-4180 escaping and duplicate suppression in WriteCSVData. A second write of the same result plus a field containing a comma/quote would make this test cover both behaviors.

Suggested test tightening
 	fields := []string{"ip", "port", "host"}
 	writer.WriteCSVRow(fields)

 	result := sources.Result{
-		IP:   "192.168.1.1",
-		Port: 80,
-		Host: "localhost",
+		IP:   "192.168.1.1",
+		Port: 80,
+		Host: `local,"host"`,
 	}

 	writer.WriteCSVData(result, fields)
+	writer.WriteCSVData(result, fields)

 	output := buf.String()
-	expectedHeader := "ip,port,host\n"
-	expectedRow := "192.168.1.1,80,localhost\n"
-
-	if !strings.Contains(output, expectedHeader) {
-		t.Errorf("Expected output to contain header %q, got %q", expectedHeader, output)
-	}
-	if !strings.Contains(output, expectedRow) {
-		t.Errorf("Expected output to contain row %q, got %q", expectedRow, output)
+	expected := "ip,port,host\n192.168.1.1,80,\"local,\"\"host\"\"\"\n"
+	if output != expected {
+		t.Errorf("Expected output %q, got %q", expected, output)
 	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@runner/runner_test.go` around lines 20 - 39, Strengthen the CSV writer test
in runner_test by verifying the behaviors implemented in WriteCSVData and
WriteCSVRow: add an input field value that requires RFC-4180 escaping (for
example, a comma or quote) and assert the written output is escaped correctly,
then call WriteCSVData twice with the same sources.Result and confirm the
duplicate row is suppressed. Use the existing writer, buf, and output assertions
to check the exact CSV output rather than only searching for a substring, so the
test covers both escaping and deduplication.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@runner/options.go`:
- Around line 225-227: The CSV default normalization in configureOutput() is
only applied before loadConfigFrom(), so config-driven csv: true values can
leave OutputFields as ip:port instead of the expected ip,port,host. Update
ParseOptions() so the CSV OutputFields rewrite is applied again after config
merging, or move the existing options.CSV and options.OutputFields check to run
after loadConfigFrom() using the same configureOutput() logic.

In `@runner/output_writer.go`:
- Around line 94-103: The duplicate suppression in the CSV writer currently uses
the endpoint-derived key in output_writer.go instead of the projected row
content, so distinct rows can be dropped when the selected fields differ. Update
the duplicate check in the row-writing path that builds dupKey and calls
findDuplicate so it derives the key from the rendered values produced by
getFieldValues for the current fields set, rather than from
data.IP/data.Port/data.Host/data.Url. This should keep deduplication aligned
with the actual CSV output while preserving the existing duplicate tracking
logic in findDuplicate.

---

Nitpick comments:
In `@runner/runner_test.go`:
- Around line 20-39: Strengthen the CSV writer test in runner_test by verifying
the behaviors implemented in WriteCSVData and WriteCSVRow: add an input field
value that requires RFC-4180 escaping (for example, a comma or quote) and assert
the written output is escaped correctly, then call WriteCSVData twice with the
same sources.Result and confirm the duplicate row is suppressed. Use the
existing writer, buf, and output assertions to check the exact CSV output rather
than only searching for a substring, so the test covers both escaping and
deduplication.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0448a451-2469-431a-9a07-a19a9f6fead3

📥 Commits

Reviewing files that changed from the base of the PR and between 3f7b74a and 2fe0576.

📒 Files selected for processing (4)
  • runner/options.go
  • runner/output_writer.go
  • runner/runner.go
  • runner/runner_test.go

Comment thread runner/options.go
Comment thread runner/output_writer.go Outdated
@ThryLox
ThryLox force-pushed the feat/csv-output branch 2 times, most recently from 17124fa to 5d8c8cc Compare June 30, 2026 05:28

@coderabbitai coderabbitai Bot left a comment

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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@runner/output_writer.go`:
- Around line 100-104: The parseFields helper is only treating a literal space
as whitespace, so tab- or newline-separated field lists are not split correctly.
Update the strings.FieldsFunc predicate in parseFields to use unicode.IsSpace
for the whitespace branch while keeping the existing comma, colon, and semicolon
separators, so output handling stays aligned with the intended whitespace
parsing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f091faca-7c80-4799-9554-92b1faa2e85d

📥 Commits

Reviewing files that changed from the base of the PR and between 17124fa and 5d8c8cc.

📒 Files selected for processing (4)
  • runner/options.go
  • runner/output_writer.go
  • runner/runner.go
  • runner/runner_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • runner/runner.go
  • runner/runner_test.go
  • runner/options.go

Comment thread runner/output_writer.go
Fixes projectdiscovery#745. Introduces a new -csv / -c flag to output results in CSV format, supporting customizable fields aligned with the -field flag (ip, port, host, url). Defaults to 'ip,port,host' if not overridden. Added unit tests for CSV serialization in the runner package.

@dogancanbakir dogancanbakir left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

LGTM -pls update README

@Mzack9999
Mzack9999 changed the base branch from main to dev July 2, 2026 21:31
@Mzack9999
Mzack9999 merged commit a2661ae into projectdiscovery:dev Jul 2, 2026
8 checks passed
@ThryLox
ThryLox deleted the feat/csv-output branch July 2, 2026 21:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add -c, --csv flag for CSV-formatted output

4 participants