fix: add DisableStdout option to suppress stdout output in SDK#1618
fix: add DisableStdout option to suppress stdout output in SDK#1618dogancanbakir merged 2 commits intodevfrom
Conversation
Adds a new DisableStdout option that allows SDK users to suppress stdout output when using the OnResult callback to handle results themselves. Closes #1414
WalkthroughAdded a Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Poem
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches
📜 Recent review detailsConfiguration used: Organization UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
pkg/runner/runner.go (1)
1129-1207: Critical: Missing stdout suppression in the HasIPS branch.The
HasIPS()case (host discovery results without port information) is missingDisableStdoutguards. WhenDisableStdoutis true, stdout output still occurs at:
- Line 1170: JSON output
- Line 1178: CSV output
- Line 1182: Plain text with CDN info
- Line 1184: Plain text without CDN info
This means the
DisableStdoutfeature doesn't work for host discovery scenarios.🔧 Proposed fix
Wrap the stdout outputs in the same conditional guard used in the
HasIPsPortsbranch:if r.options.JSON || r.options.CSV { data := &Result{IP: hostIP, TimeStamp: time.Now().UTC(), MacAddress: macAddress} if r.options.OutputCDN { data.IsCDNIP = isCDNIP data.CDNName = cdnName } if host != hostIP { data.Host = host } - if r.options.JSON { - b, err := data.JSON(r.options.ExcludeOutputFields) - if err != nil { - continue - } - buffer.Write([]byte(fmt.Sprintf("%s\n", b))) - gologger.Silent().Msgf("%s", buffer.String()) - } else { - if csvFileHeaderEnabled { - writeCSVHeaders(data, writer, r.options.ExcludeOutputFields) - csvFileHeaderEnabled = false - } - writeCSVRow(data, writer, r.options.ExcludeOutputFields) - writer.Flush() - gologger.Silent().Msgf("%s", buffer.String()) - } + if !r.options.DisableStdout { + if r.options.JSON { + b, err := data.JSON(r.options.ExcludeOutputFields) + if err != nil { + continue + } + buffer.Write([]byte(fmt.Sprintf("%s\n", b))) + gologger.Silent().Msgf("%s", buffer.String()) + } else { + if csvFileHeaderEnabled { + writeCSVHeaders(data, writer, r.options.ExcludeOutputFields) + csvFileHeaderEnabled = false + } + writeCSVRow(data, writer, r.options.ExcludeOutputFields) + writer.Flush() + gologger.Silent().Msgf("%s", buffer.String()) + } + } } else { - if r.options.OutputCDN && isCDNIP { - gologger.Silent().Msgf("%s [%s]\n", host, cdnName) - } else { - gologger.Silent().Msgf("%s\n", host) + if !r.options.DisableStdout { + if r.options.OutputCDN && isCDNIP { + gologger.Silent().Msgf("%s [%s]\n", host, cdnName) + } else { + gologger.Silent().Msgf("%s\n", host) + } } }
🧹 Nitpick comments (1)
pkg/runner/runner.go (1)
254-269: LGTM!The conditional guard correctly suppresses JSON, CSV, and plain text output to stdout when
DisableStdoutis enabled. All three output formats are properly handled.💡 Optional performance optimization
When
DisableStdoutis true and no file output is configured, the JSON/CSV formatting work (lines 225-253) is unnecessary since the buffer is only used for stdout in this function. Consider moving the formatting inside the stdout guard or adding an early check to skip formatting when output won't be used:- if r.options.JSON || r.options.CSV { + if (r.options.JSON || r.options.CSV) && !r.options.DisableStdout { data := &Result{IP: hostResult.IP, TimeStamp: time.Now().UTC(), MacAddress: hostResult.MacAddress} // ... formatting logic ... } - if !r.options.DisableStdout { + if !r.options.DisableStdout && (r.options.JSON || r.options.CSV) { if r.options.JSON { gologger.Silent().Msgf("%s", buffer.String()) // ...
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
pkg/runner/options.gopkg/runner/runner.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: build-mac
- GitHub Check: build-linux
- GitHub Check: build-windows
- GitHub Check: Functional Test (ubuntu-latest)
- GitHub Check: release-test-windows
- GitHub Check: release-test-mac
- GitHub Check: Analyze (go)
🔇 Additional comments (3)
pkg/runner/options.go (1)
37-37: LGTM!The
DisableStdoutfield is well-documented and appropriately named. The comment clearly explains its purpose for SDK usage.pkg/runner/runner.go (2)
1099-1107: LGTM!The conditional guard correctly suppresses JSON and CSV output to stdout in the
HasIPsPortsbranch whenDisableStdoutis enabled.
1046-1046: These Info-level messages appear to follow intentional design separate from result suppression.The
gologger.Info()messages at lines 1046 and 1147 are consistently not wrapped inDisableStdoutguards throughout the codebase, unlike the actual result output which usesgologger.Silent()and IS guarded (lines 256-265, 1101-1105, 1170-1184). Other Info messages like "Skipping" at lines 370 and 574 follow the same pattern.This suggests the implementation deliberately separates status/progress messages (Info) from result output (Silent). If SDK users need complete stdout control including these status messages, that would be a separate feature request rather than an oversight.
| } else if r.options.CSV { | ||
| writer := csv.NewWriter(&buffer) | ||
| writer.Flush() | ||
| gologger.Silent().Msgf("%s", buffer.String()) |
There was a problem hiding this comment.
seems writer.Flush() redundant in new writer as nothing to flush, or we can use exiting writer than its fine,. though its not related to this pr :)
dwisiswant0
left a comment
There was a problem hiding this comment.
Maybe we should gate this behind an environment variable so the CLI benefits too?
A similar issue happened in projectdiscovery/nuclei#6060, where stdio pollution interfered with parsing benchmark / MCP outputs.
Summary
DisableStdoutoption to suppress stdout output when using the SDKOnResultcallback without duplicate stdout printingCloses #1414
Usage
Test plan
DisableStdout: truein SDK usageOnResultcallback still receives resultsSummary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.