Skip to content

fix(output): ensure -eof completely omit fields from JSON output#1546

Merged
Mzack9999 merged 2 commits intoprojectdiscovery:devfrom
hanXen:fix/eof-json
Aug 27, 2025
Merged

fix(output): ensure -eof completely omit fields from JSON output#1546
Mzack9999 merged 2 commits intoprojectdiscovery:devfrom
hanXen:fix/eof-json

Conversation

@hanXen
Copy link
Copy Markdown
Contributor

@hanXen hanXen commented Aug 27, 2025

Resolves #1545
Depends on projectdiscovery/utils#674

Summary

This PR fixes a bug where the -eof flag set fields to their zero-value (e.g., "timestamp": "0001-01-01...") instead of omitting them from the JSON output.

This is resolved by using a new structs.FilterStructToMap utility function, which is being introduced in the companion projectdiscovery/utils PR.

Solution

To ensure excluded fields are truly omitted, JSON() in pkg/runner/output.go now calls structs.FilterStructToMap. This helper converts the result struct into a map[string]any and removes entries for excluded json keys (respecting omitempty) before json.Marshal is called, ensuring fields specified by -eof are absent from the final JSON output.

Additionally, this fix includes a necessary internal change to ensure -eof port works as expected. The internal DTO field PortNumber was renamed to Port to align with the user-facing field list from -lof. This is a safe modification that does not change the final JSON output key, which remains "port".

Development & Testing Notes

To test this PR before the dependency in projectdiscovery/utils is merged, the go.mod file was temporarily modified with a replace directive. This directive should be removed once the dependency PR is merged.

replace github.com/projectdiscovery/utils => github.com/hanxen/proj.discov_utils v0.4.24-0.20250826105743-08b0e6969365

Summary by CodeRabbit

  • Refactor

    • Optimized JSON output so serialization is faster when no fields are excluded; improved robustness of field-exclusion filtering and ensured consistent port values in JSON output.
  • Chores

    • Upgraded several dependencies for stability and compatibility.
    • Adjusted module resolution to improve build reliability.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Aug 27, 2025

Walkthrough

Dependency updates in go.mod (including a replace for projectdiscovery/utils). pkg/runner/output.go switches JSON exclusion handling to a map-based path when exclusions are present and renames internal jsonResult field PortNumberPort. Public APIs unchanged.

Changes

Cohort / File(s) Summary
Dependency Management
go.mod
Updated dependencies (e.g., github.com/projectdiscovery/retryablehttp-go bumped) and added a replace directive pointing github.com/projectdiscovery/utilsgithub.com/hanxen/proj.discov_utils@....
JSON Output & Runner
pkg/runner/output.go
Renamed internal jsonResult field PortNumberPort and adjusted assignments. JSON() now returns json.Marshal(data) when no excluded fields; when exclusions exist it uses FilterStructToMap and marshals the resulting map (map-based filtering). WriteJSONOutput updated to use data.Port. No exported type/function signatures changed.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  participant Runner
  participant JSON as jsonResult.JSON()
  participant Filter as FilterStructToMap
  participant Marshal as json.Marshal

  Runner->>JSON: construct jsonResult (data)
  alt no excluded fields
    JSON->>Marshal: Marshal(struct data)
    Marshal-->>Runner: bytes / error
  else excluded fields present
    JSON->>Filter: FilterStructToMap(struct data, exclusions)
    alt filter success
      JSON->>Marshal: Marshal(filtered map)
      Marshal-->>Runner: bytes / error
    else filter error
      JSON-->>Runner: error
    end
  end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Assessment against linked issues

Objective Addressed Explanation
Omit excluded fields entirely from JSON output with -eof (-exclude-output-fields) [#1545]
Ensure excluded fields like timestamp, protocol, tls do not appear when filtered using -j with -eof [#1545]

Out-of-scope changes

Code Change Explanation
Added replace directive for github.com/projectdiscovery/utils -> github.com/hanxen/proj.discov_utils (go.mod) This changes module resolution/source for a dependency; unrelated to the JSON filtering bug fix objective and may affect builds.

I nibbled fields clean, with a tidy hop,
Mapped away zeros — a quiet crop.
Ports stay true, while ghosts depart,
JSON trimmed neat, a rabbit's art.
Hoppity hop, the output's smart! 🥕✨


📜 Recent 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 97db5b4 and 8bdb812.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (1)
  • go.mod (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • go.mod
✨ Finishing Touches
🧪 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 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

@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

📜 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 b4eef03 and 97db5b4.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (2)
  • go.mod (4 hunks)
  • pkg/runner/output.go (3 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
pkg/runner/output.go (1)
pkg/port/port.go (1)
  • Port (10-17)
🔇 Additional comments (5)
go.mod (2)

23-25: Dependency Updates Approved: Patch-Level Bumps Only

The following ProjectDiscovery modules have been bumped in go.mod:

  • Direct dependencies

    • github.com/projectdiscovery/networkpolicy → v0.1.20
    • github.com/projectdiscovery/retryablehttp-go → v1.0.120
  • Indirect dependencies

    • github.com/projectdiscovery/fastdialer → v0.4.6
    • github.com/projectdiscovery/hmap → v0.0.92
    • github.com/projectdiscovery/retryabledns → v1.0.105

These are all low-risk, patch-level updates. No breaking changes are expected. Please ensure you’ve skimmed the corresponding release notes and run the full integration test suite to catch any edge-case regressions before merging.


27-27: The script will check that the upstream structs.FilterStructToMap exists on main but that no v0.4.24 release is yet published (latest is v0.4.23), indicating we must hold the temporary replace until the official v0.4.24 tag is cut. Once confirmed, update the review to:

  • Note that v0.4.24 is not yet released (latest v0.4.23).

  • Keep the replace in place until the release is cut.

  • After the utils repo publishes v0.4.24 with FilterStructToMap, update go.mod:

    - github.com/projectdiscovery/utils v0.4.22
    + github.com/projectdiscovery/utils v0.4.24

    and drop the replace.

This ensures consumers aren’t pinned to a non-canonical fork and can smoothly upgrade once the official module is available.

pkg/runner/output.go (3)

36-44: jsonResult shape aligns with external schema; port rename reflected.

Tags are correct; keeping port/protocol/tls non-omitempty ensures presence unless explicitly excluded.


59-61: Map-based filtering and test coverage verification

The switch to a map for excluding JSON keys correctly omits unwanted fields, but marshaling a map may emit keys in a nondeterministic order. Additionally, there’s no evidence of existing tests covering the JSON() method with various ExcludeOutputFields combinations (only a single call at pkg/runner/runner.go:232 was found, and no corresponding tests were located).

• Potential nondeterministic key order when using json.Marshal on a map.
• No tests detected for data.JSON(r.options.ExcludeOutputFields) edge cases—coverage should be confirmed or added.
• Optional refactor if downstream tooling/tests require stable ordering:
– Construct and marshal an ordered struct with fields in a fixed sequence, or
– Manually encode JSON by iterating over a sorted slice of keys.
• Otherwise, update or add tests to accept any key order (order-agnostic assertions).

Please verify test coverage for excluded-fields scenarios and adjust accordingly.


55-55: Migration complete – no stale PortNumber references remain.

  • Searched for PortNumber (exact match) across the codebase; no occurrences found.
  • Checked for lowercase portNumber usages; the only hits are local variables in pkg/runner/ports.go (lines 180–184), which are unrelated to the struct field migration.
  • Verified there are no lingering JSON or YAML tags referencing portNumber.

All references to the old field name have been removed.

Comment thread pkg/runner/output.go
}
for _, p := range ports {
data.PortNumber = p.Port
data.Port = p.Port
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

WriteJSONOutput still ignores -eof; confirm call-site filtering or plumb exclusions.

If no upstream layer filters before Encode, JSON streaming output will not honor -eof.

If needed, add a variant that accepts excludedFields and reuses the map-filter path to ensure consistency between r.JSON() and streaming.


🏁 Script executed:

#!/bin/bash
# Find call sites and see if excluded fields are applied on the streaming path
rg -nP '\bWriteJSONOutput\s*\(' -C3
rg -nP 'excludedFields|eof' -n -C2

Length of output: 5991


Ensure JSON streaming honors -eof exclude-output-fields

  • The WriteJSONOutput function (pkg/runner/output.go:134–137) does not accept an excludedFields slice, so it never applies the -eof filter on its output.
  • All call-sites in pkg/runner/runner.go (lines 1027 and 1089) invoke WriteJSONOutput without filtering, unlike WriteCsvOutput which correctly takes and applies r.options.ExcludeОutputFields.

Recommended change:

  • Extend WriteJSONOutput (and its helper types) to accept excludedFields []string and, before calling json.NewEncoder, filter the data (e.g. via structs.FilterStructToMap) as is done in (*Result).JSON(). This will ensure parity between JSON and CSV output formats.
🤖 Prompt for AI Agents
In pkg/runner/output.go around lines 134–147, WriteJSONOutput currently doesn't
accept excludedFields so the -eof exclude-output-fields filter is never applied;
change WriteJSONOutput signature to accept excludedFields []string (and update
any helper types/functions in this file) and, before creating json.NewEncoder,
convert or filter the value to a map using the same filtering used by
(*Result).JSON() (e.g. call structs.FilterStructToMap(value, excludedFields) or
equivalent) so excluded fields are removed, then pass the filtered map to the
encoder; finally update the two callers in pkg/runner/runner.go (around lines
1027 and 1089) to pass r.options.ExcludeOutputFields to the updated
WriteJSONOutput.

@Mzack9999 Mzack9999 self-requested a review August 27, 2025 17:10
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.

Fields are not completely omitted from JSON output when using -eof flag

2 participants