Repository navigation
Add greppable output (spoonmap_output.gnmap) - #38
Merged
Merged
Conversation
Collaborator
Author
|
Note on merge order: this and #37 are independent features branched from the same So whichever of #37/#38 merges second needs a trivial conflict resolution — keep both test blocks, keep both import lines. Happy to rebase whichever one you'd rather take second; just say which and I'll push the update. |
bandrel
force-pushed
the
feat/gnmap-output
branch
from
August 21, 2026 16:25
ada4124 to
597f66c
Compare
Closes #36. Originally proposed in PR #11 (Feb 2021), closed as unmergeable. Each port's banner pass now writes nmap_results/portN.gnmap via -oG, and those are merged into spoonmap_output.gnmap after the workers join. Why not #11's approach: it pointed every port at one shared -oG file with --append-output. That was safe when nmap ran serially, but nmap_scan() now runs five concurrent workers, so five processes would interleave their appends into a plausible-looking but corrupt host list — the worst outcome for a format whose whole purpose is machine consumption. One file per port gives each a single writer. Merged, not concatenated: a host open on three ports is scanned by three nmap runs and so appears in three files, but grepable output is one line per host. Concatenating would make anything counting lines over-count hosts and would disagree with spoonmap_output.xml/.json, which merge the same hosts. Hosts are ordered by _ip_sort_key() and port entries numerically, so the file is stable across runs and diffable between scans. Two consistency details: - _quarantine_failed_output() now renames the sibling .gnmap too. Otherwise a port excluded from spoonmap_output.xml would still contribute its partial hosts to spoonmap_output.gnmap, leaving the greppable artifact the more optimistic of the two about what was actually scanned. - Ports holding an .xml with no .gnmap — what a resume from before this feature looks like — are named in a warning instead of being silently absent. An artifact that quietly covers less than the run did is a coverage claim the scan never made. port{N}_sql.xml is excluded from that check, since _scan_extra_sql_ports() writes it with no -oG and it is not a gap. Adding .gnmap to nmap_results/ is safe for existing readers: all three that scan the directory filter on an .xml extension, and _parse_result_xml() returns None for anything else. spoonmap_output.gnmap is registered in _RESULT_FILES so --cleanup removes it. The parser was verified against real nmap 7.99 -oG output, not just a fixture: tab-separated fields, the 'Status: Up' line emitted alongside the ports line, the trailing 'Ignored State' field, and the comment header/footer. 939 tests pass (32 new), 100% coverage. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bandrel
force-pushed
the
feat/gnmap-output
branch
from
August 21, 2026 16:29
597f66c to
589ac1d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #36. Implements the idea from PR #11 (Feb 2021, @zenfosec), which I closed as unmergeable.
What this adds
Each port's banner pass writes
nmap_results/portN.gnmapvia-oG, and those are merged intospoonmap_output.gnmaponce the workers join:Why not #11's approach
#11 pointed every port at a single shared
-oGfile with--append-output. That was safe when nmap ran serially.nmap_scan()now runs five concurrent workers by default, so five nmap processes would be appending to one file simultaneously and interleaving their writes — producing a plausible-looking but corrupt host list. For a format whose entire purpose is machine consumption, silently corrupt is worse than absent. One file per port gives each a single writer.Merged, not concatenated
A host open on three ports is scanned by three separate nmap runs, so it appears in three per-port files. Grepable output is one line per host, so those are merged rather than concatenated. Concatenating would make anything counting lines over-count hosts, and would put this artifact at odds with
spoonmap_output.xml/.json, which merge the same hosts.Hosts come out in numeric IP order (
_ip_sort_key()) and port entries in numeric port order, so the file is stable across runs and diffable between scans.Two consistency details worth review
A quarantined port's
.gnmapis quarantined too._quarantine_failed_output()renames the sibling.gnmapalongside the.xml. Without that, a port excluded fromspoonmap_output.xmlfor a failed nmap exit would still contribute its partial hosts tospoonmap_output.gnmap— the two artifacts would disagree about what was scanned, and the greppable one would be the optimistic of the two. There's a test asserting the quarantined data doesn't reach the aggregate.Ports with
.xmlbut no.gnmapare named, not dropped. That's what resuming a scan from before this feature looks like. An artifact that quietly covers less than the run did is a coverage claim the scan never made, so it warns and points atspoonmap_output.xml.port{N}_sql.xmlis excluded from that check —_scan_extra_sql_ports()writes it with no-oG, so it isn't a gap.Safety for existing readers
Adding
.gnmapfiles tonmap_results/doesn't disturb anything: all three call sites that scan that directory filter on an.xmlextension, and_parse_result_xml()returns None for anything else (no warning spam).spoonmap_output.gnmapis registered in_RESULT_FILES, so--cleanupremoves it.Scope is the banner pass only. The NSE script pass writes to its own directory and its results are surfaced as findings, so a
-oGthere would duplicate without adding anything greppable.Verification
-oGoutput, not just fixtures — confirming the tab-separated field layout, theStatus: Upline nmap emits alongside the ports line for the same host, the trailingIgnored Statefield, and the comment header/footer. The fixtures were then written to match what nmap actually produces.🤖 Generated with Claude Code