fix: prevent nmap service info from being copied to unrelated ports#1613
fix: prevent nmap service info from being copied to unrelated ports#1613Mzack9999 merged 3 commits intoprojectdiscovery:devfrom
Conversation
WalkthroughWriteJSONOutputWithMac and WriteCsvOutputWithMac now delegate service-field copying/clearing to a new helper, copyServiceFields, which copies all service-related fields when Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~12 minutes Poem
Pre-merge checks and finishing touches❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pkg/runner/output.go (1)
226-259: Consider extracting service field logic to reduce duplication.The service field copying and clearing logic (lines 226-259) is duplicated in
WriteCsvOutputWithMac(lines 303-336). Consider extracting this into a helper method to improve maintainability.🔎 Example refactor with helper methods
Add these helper methods to the file:
// copyServiceToResult copies service fields from port.Service to Result func copyServiceToResult(result *Result, service *port.Service) { result.DeviceType = service.DeviceType result.ExtraInfo = service.ExtraInfo result.HighVersion = service.HighVersion result.Hostname = service.Hostname result.LowVersion = service.LowVersion result.Method = service.Method result.Name = service.Name result.OSType = service.OSType result.Product = service.Product result.Proto = service.Proto result.RPCNum = service.RPCNum result.ServiceFP = service.ServiceFP result.Tunnel = service.Tunnel result.Version = service.Version result.Confidence = service.Confidence } // clearServiceFields clears all service-related fields in Result func clearServiceFields(result *Result) { result.DeviceType = "" result.ExtraInfo = "" result.HighVersion = "" result.Hostname = "" result.LowVersion = "" result.Method = "" result.Name = "" result.OSType = "" result.Product = "" result.Proto = "" result.RPCNum = "" result.ServiceFP = "" result.Tunnel = "" result.Version = "" result.Confidence = 0 }Then replace the duplicated logic:
// copy the service fields if p.Service != nil { - result.DeviceType = p.Service.DeviceType - result.ExtraInfo = p.Service.ExtraInfo - result.HighVersion = p.Service.HighVersion - result.Hostname = p.Service.Hostname - result.LowVersion = p.Service.LowVersion - result.Method = p.Service.Method - result.Name = p.Service.Name - result.OSType = p.Service.OSType - result.Product = p.Service.Product - result.Proto = p.Service.Proto - result.RPCNum = p.Service.RPCNum - result.ServiceFP = p.Service.ServiceFP - result.Tunnel = p.Service.Tunnel - result.Version = p.Service.Version - result.Confidence = p.Service.Confidence + copyServiceToResult(result, p.Service) } else { - // Clear service fields if no service information exists - result.DeviceType = "" - result.ExtraInfo = "" - result.HighVersion = "" - result.Hostname = "" - result.LowVersion = "" - result.Method = "" - result.Name = "" - result.OSType = "" - result.Product = "" - result.Proto = "" - result.RPCNum = "" - result.ServiceFP = "" - result.Tunnel = "" - result.Version = "" - result.Confidence = 0 + clearServiceFields(result) }Apply the same pattern to
WriteCsvOutputWithMac.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
pkg/runner/output.go
🧰 Additional context used
🧬 Code graph analysis (1)
pkg/runner/output.go (1)
pkg/port/port.go (1)
Service(35-51)
🔇 Additional comments (2)
pkg/runner/output.go (2)
242-259: Fix correctly prevents service information leakage.The else block properly clears all 15 service-related fields when
p.Service == nil, preventing carryover from previous iterations. This directly addresses the bug described in the PR objectives.
301-337: CSV output correctly mirrors JSON fix.The service field handling in
WriteCsvOutputWithMacis consistent withWriteJSONOutputWithMac, ensuring both output formats prevent service information leakage. The added blank lines improve code readability.
Additional NotesThis issue can be observed when running: sudo ./naabu -host 192.168.1.117 -port 22,2080,5173,5432 -nmap-cli 'nmap -sV' -json -o testTerminal output correctly shows only port 22 with service info. |
|
I couldn't repro this |
|
https://asciinema.org/a/7XShK6J7x4dpLLGuN6ZSjmE2G |
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pkg/runner/output.go (1)
304-329: LGTM! Helper function correctly addresses the service leak bug.The implementation correctly handles both cases:
- When
serviceis not nil, all 15 service fields are copied to the result- When
serviceis nil, copying from an emptyport.Service{}clears all fields using zero valuesThis centralized approach eliminates the code duplication flagged in the previous review and ensures consistent behavior across JSON and CSV output paths.
💡 Optional: Minor simplification
The local variable
scould be eliminated by directly handling both branches, though the current approach is perfectly clear:func copyServiceFields(result *Result, service *port.Service) { if service == nil { service = &port.Service{} } result.DeviceType = service.DeviceType result.ExtraInfo = service.ExtraInfo // ... rest of fields }However, modifying the parameter might be considered less idiomatic, so the current implementation is fine.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
pkg/runner/output.go
🧰 Additional context used
🧬 Code graph analysis (1)
pkg/runner/output.go (2)
pkg/port/port.go (1)
Service(35-51)pkg/result/results.go (1)
Result(39-44)
🔇 Additional comments (2)
pkg/runner/output.go (2)
225-226: LGTM! Service field leak fixed for JSON output.The centralized helper correctly copies service fields when present or clears them when
p.Serviceis nil, preventing service data from leaking to subsequent ports.
268-270: LGTM! Service field leak fixed for CSV output.Consistent with the JSON output path, this correctly delegates service field handling to the centralized helper.
There was a problem hiding this comment.
Actionable comments posted: 0
🧹 Nitpick comments (1)
pkg/runner/output.go (1)
302-326: LGTM! The helper correctly handles both copying and clearing service fields.The function properly addresses the service info leak by ensuring all service fields are set to zero values when
serviceis nil. All 15 fields fromport.Serviceare accounted for, and the implementation is straightforward.💡 Optional: Minor simplification
The intermediate variable
scould be eliminated for slightly more concise code:func copyServiceFields(result *Result, service *port.Service) { - var s *port.Service - if service != nil { - s = service - } else { - s = &port.Service{} + if service == nil { + service = &port.Service{} } - result.DeviceType = s.DeviceType - result.ExtraInfo = s.ExtraInfo + result.DeviceType = service.DeviceType + result.ExtraInfo = service.ExtraInfo // ... (apply to all remaining fields)The current implementation is perfectly correct, so this is purely a style preference.
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
pkg/runner/output.go
🧰 Additional context used
🧬 Code graph analysis (1)
pkg/runner/output.go (1)
pkg/port/port.go (1)
Service(35-51)
🔇 Additional comments (2)
pkg/runner/output.go (2)
225-225: LGTM! Correctly delegates service field handling to the helper.This change ensures that when
p.Serviceis nil, all service fields are cleared rather than retaining values from the previous iteration, which was the root cause of the service info leak bug.
267-268: LGTM! Consistent fix applied to CSV output path.The same helper is used for both JSON and CSV outputs, ensuring the service info leak bug is fixed consistently across all output formats.
|
@yutianqaq Appreciate the contribution. Nice work on this change. |
|
@coderabbitai create an issue for this PR |
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: Length of output: 53 @Mzack9999: I've created issue #1624 for this PR: #1624 The issue describes the bug where nmap service information was leaking to unrelated ports and includes a backlink to this PR. |
Problem
When using naabu with nmap integration (
-nmap-cli), service information was being incorrectly copied to ports that don't have service data from nmap.Example:
Before fix:
{"ip":"192.168.1.117","port":22,"extra_info":"protocol 2.0","name":"ssh","product":"OpenSSH","version":"10.0p2 Debian 5"} {"ip":"192.168.1.117","port":2080,"extra_info":"protocol 2.0","name":"ssh","product":"OpenSSH","version":"10.0p2 Debian 5"} // Wrong! {"ip":"192.168.1.117","port":5173,"extra_info":"protocol 2.0","name":"ssh","product":"OpenSSH","version":"10.0p2 Debian 5"} // Wrong!After fix:
{"ip":"192.168.1.117","port":22,"extra_info":"protocol 2.0","name":"ssh","product":"OpenSSH","version":"10.0p2 Debian 5"} {"ip":"192.168.1.117","port":2080} // Correct - no service info {"ip":"192.168.1.117","port":5173} // Correct - no service infoRoot Cause
In
pkg/runner/output.go, theResultstruct was reused across port iterations. When a port had no service info (p.Service == nil), the service fields from the previous port were not cleared, causing data leakage.Solution
Added
elseblocks to clear all service-related fields whenp.Service == nilin both:WriteJSONOutputWithMac()- for JSON outputWriteCsvOutputWithMac()- for CSV outputChanges
pkg/runner/output.goTesting
Tested with port 22 (with SSH service info) followed by ports 2080, 5173 (no service info):
Summary by CodeRabbit
✏️ Tip: You can customize this high-level summary in your review settings.