mirror of
https://github.com/reconurge/flowsint.git
synced 2026-07-17 01:24:19 -05:00
[PR #184] feat(imports): add nmap XML importer #2874
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
📋 Pull Request Information
Original PR: https://github.com/reconurge/flowsint/pull/184
Author: @rachit367
Created: 6/9/2026
Status: 🔄 Open
Base:
main← Head:feat/nmap-xml-importer📝 Commits (1)
f9100bafeat(imports): add nmap XML importer📊 Changes
8 files changed (+314 additions, -4 deletions)
View changed files
📝
flowsint-api/app/api/routes/sketches.py(+4 -2)📝
flowsint-app/src/components/sketches/import-sheet.tsx(+1 -1)📝
flowsint-core/pyproject.toml(+1 -0)📝
flowsint-core/src/flowsint_core/imports/file_parser.py(+4 -1)➕
flowsint-core/src/flowsint_core/imports/nmap/__init__.py(+3 -0)➕
flowsint-core/src/flowsint_core/imports/nmap/parse_nmap.py(+150 -0)➕
flowsint-core/tests/import/nmap/test_nmap_import.py(+140 -0)📝
uv.lock(+11 -0)📄 Description
What
Adds an nmap XML importer so an existing scan can be imported into a sketch, instead of re-scanning a target or adding ports by hand.
Closes #107
Why
From the issue: during assessments people often run nmap manually with specific flags, and naabu can also export in nmap XML. Letting Flowsint ingest that XML enriches a sketch with the hosts/ports already discovered. This reuses the existing two-phase import pipeline (analyze → execute) — no new infrastructure.
How it plugs in
The import pipeline dispatches parsers by file extension (
flowsint_core/imports/file_parser.py) and each parser is a function returning aFileParseResultof typed entities + edges, which the pipeline persists. The new parser follows that exact contract (same shape as the existing JSON parser).flowsint_core/imports/nmap/parse_nmap.py(new) —parse_nmap_xml()turns an nmap report into:Ipentities (one per up host; down hosts skipped; IPv4 preferred, IPv6 supported, MAC ignored)Portentities (number,protocol,state,service, and abannercomposed from serviceproduct/version/extrainfo)IP -[HAS_PORT]-> Portedges (the same relationship label theip_to_portsenricher uses).xmladded toALLOWED_EXTENSIONS(core dispatcher) + the analyze route's filename validation (flowsint-api/.../sketches.py) + the import sheet's accepted extensions (flowsint-app/.../import-sheet.tsx).IpandPortalready exist, so no type changes were needed.Security
Import files are untrusted, so the XML is parsed with
defusedxml(newflowsint-coredependency) to prevent XXE / billion-laughs attacks. Element type hints still come from the stdlib (identical types, not a parsing path).Testing
New tests (pure-parse, no DB): IP/port extraction, port fields + banner composition,
HAS_PORTedges, down-host skipping, IPv6, invalid-port skipping, empty/invalid XML handling, and dispatch throughparse_import_file.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.