Skip to content

fix: add DisableStdout option to suppress stdout output in SDK#1618

Merged
dogancanbakir merged 2 commits intodevfrom
fix/disable-stdout-sdk
Jan 5, 2026
Merged

fix: add DisableStdout option to suppress stdout output in SDK#1618
dogancanbakir merged 2 commits intodevfrom
fix/disable-stdout-sdk

Conversation

@dogancanbakir
Copy link
Copy Markdown
Member

@dogancanbakir dogancanbakir commented Jan 5, 2026

Summary

  • Adds a new DisableStdout option to suppress stdout output when using the SDK
  • Allows SDK users to handle results via OnResult callback without duplicate stdout printing

Closes #1414

Usage

options := runner.Options{
    Host:          []string{"example.com"},
    Ports:         "80,443",
    DisableStdout: true,
    OnResult: func(hr *result.HostResult) {
        // Handle result yourself
    },
}

Test plan

  • Set DisableStdout: true in SDK usage
  • Verify no output is printed to stdout
  • Verify OnResult callback still receives results

Summary by CodeRabbit

  • New Features
    • Added a configuration option (can be enabled via the DISABLE_STDOUT environment variable) to suppress standard output, allowing integrations to consume results via callbacks or other channels without console output interference. Default behavior unchanged.

✏️ Tip: You can customize this high-level summary in your review settings.

Adds a new DisableStdout option that allows SDK users to suppress
stdout output when using the OnResult callback to handle results
themselves.

Closes #1414
@auto-assign auto-assign bot requested a review from dwisiswant0 January 5, 2026 09:58
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Jan 5, 2026

Walkthrough

Added a DisableStdout boolean to Options and added conditional guards around all stdout printing paths so that JSON, CSV, and plain-text output are skipped when the flag is enabled (including outputs from onReceive and handleOutput code paths).

Changes

Cohort / File(s) Summary
Options field
pkg/runner/options.go
Added public DisableStdout bool to Options and initialize it from the DISABLE_STDOUT environment variable during option parsing.
Stdout suppression guards
pkg/runner/runner.go
Wrapped all console printing (JSON, CSV, plain text) in conditional checks to skip writes when Options.DisableStdout is true; applied in both result receive and output handling paths.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰
A quiet hop, a gentle tweak,
I stitched a switch so outputs leak not,
Callbacks hum and results you keep,
No noisy console, silence sweet —
I nibble code and dance with joy.

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main change: adding a DisableStdout option to suppress stdout output, which directly addresses the PR's primary objective.
Linked Issues check ✅ Passed The PR implements the core requirement from #1414 by adding DisableStdout field and guarding stdout output, allowing SDK users to suppress automatic printing and use OnResult callback instead.
Out of Scope Changes check ✅ Passed All changes are directly related to implementing the DisableStdout feature for suppressing stdout output as specified in the linked issue #1414.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between d1f4dac and 137b005.

📒 Files selected for processing (1)
  • pkg/runner/options.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/runner/options.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). (5)
  • GitHub Check: build-mac
  • GitHub Check: build-windows
  • GitHub Check: build-linux
  • GitHub Check: Functional Test (ubuntu-latest)
  • GitHub Check: Analyze (go)

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: 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 missing DisableStdout guards. When DisableStdout is 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 DisableStdout feature doesn't work for host discovery scenarios.

🔧 Proposed fix

Wrap the stdout outputs in the same conditional guard used in the HasIPsPorts branch:

 				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 DisableStdout is enabled. All three output formats are properly handled.

💡 Optional performance optimization

When DisableStdout is 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

📥 Commits

Reviewing files that changed from the base of the PR and between 9976c32 and d1f4dac.

📒 Files selected for processing (2)
  • pkg/runner/options.go
  • pkg/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 DisableStdout field 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 HasIPsPorts branch when DisableStdout is 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 in DisableStdout guards throughout the codebase, unlike the actual result output which uses gologger.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.

Comment on lines +1102 to +1105
} else if r.options.CSV {
writer := csv.NewWriter(&buffer)
writer.Flush()
gologger.Silent().Msgf("%s", buffer.String())
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.

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 :)

Copy link
Copy Markdown
Member

@dwisiswant0 dwisiswant0 left a comment

Choose a reason for hiding this comment

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

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.

@dogancanbakir dogancanbakir merged commit 69d9764 into dev Jan 5, 2026
13 checks passed
@dogancanbakir dogancanbakir deleted the fix/disable-stdout-sdk branch January 5, 2026 12:34
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.

SDK is always printing to stdout

3 participants