Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dmap

Overview

dmap (delta map) is a command-line tool for running nmap against one host and comparing historical scan data to detect anomalies. Use it to see what changed since the last comparable scan, or since a baseline scan of your choice. With enough prior runs it can also call out when the current result looks unlike your recent pattern for that host. Use only on hosts and networks you own or are explicitly authorized to test.

Source: github.com/dsdugal/dmap

The package is not published on PyPI yet. See Installation for how to get started.

Features

  • Single-target runs — One host per run; extra nmap arguments via -e.
  • History and diff — SQLite snapshots under a configurable data directory; each run has a stable scan_id (UUID) and profile. Compare to the previous run for the same target/profile or pin --baseline-scan-id. See Evidence bundle JSON.
  • IsolationForest — With enough prior scans, attaches ml_score / ml_is_outlier; training window and minimum history via Environment.
  • Scripting — Versioned stdout JSON (schema_version 1.0); -q hides it without changing exits. Codes 0 / 1 / 2Exit codes.

Requirements

  • Python 3.11+ (see requires-python in pyproject.toml)
  • nmap on PATH (override with NMAP_BINARY or other DMAP_ settings)

Installation

git clone https://github.com/dsdugal/dmap.git
cd dmap
python3 -m venv .venv && source .venv/bin/activate   # Windows: .\.venv\Scripts\activate
pip install .

That installs the dmap CLI and runtime dependencies only.

Optional — isolated CLI without managing a venv: pipx can install from the default branch of the repository:

pipx install "git+https://github.com/dsdugal/dmap.git"

Pin a tag or commit in the URL (e.g. @v0.1.0) when you need a reproducible install.

Use

dmap run 203.0.113.10 -e "-p 22,80 -sV"
echo $?   # see Exit codes

Environment (optional)

Variable Description
DMAP_DATA_DIR Directory containing snapshots.sqlite3 (default: ~/.local/share/dmap)
NMAP_BINARY Path to the nmap executable
DMAP_HISTORY_K Max prior snapshots used to fit the isolation forest (default: 32)
DMAP_MIN_TRAIN Minimum history rows before ml_score is computed (default: 5)
DMAP_NMAP_TIMEOUT_SEC Subprocess timeout for nmap in seconds (default: 600)

Flags

  • --baseline-scan-id UUID — diff against that stored scan instead of the latest snapshot
  • --fail-on-diff-rule — exit 2 if a new open TCP port appears (useful when ML is cold)
  • -q / --quiet — suppress JSON on stdout (exit code unchanged)

Exit codes

Exit codes separate a clean outcome, failures, and cases that should be treated as a meaningful change. The dmap run process uses the following exit codes:

Code Meaning
0 Clean — no material diff and isolation forest did not flag an outlier (and --fail-on-diff-rule did not force material).
1 Error — invalid target, baseline not found, nmap failure, I/O error, or other runtime failure (message on stderr).
2 Material — at least one deterministic diff row, or ml_is_outlier is true, or --fail-on-diff-rule fired on a new open TCP port.

Evidence bundle JSON (schema_version 1.0)

Each successful dmap run prints one JSON object (unless -q). Fields are defined in src/dmap/schema.py.

Field Type Description
schema_version string Always "1.0" for this contract.
scan_id string UUID for this scan row (also primary key in SQLite).
target_key string Validated single target (hostname or IP).
profile_id string Stable hash of profile_extra_args (scan “profile”).
profile_extra_args string Extra nmap flags passed with -e (normalized trim).
wall_time_utc string ISO 8601 UTC timestamp when the bundle was built.
nmap_version string or null From nmap XML when present.
ml_score number or null Anomaly score: higher = more anomalous; null when history is shorter than DMAP_MIN_TRAIN or empty.
ml_is_outlier boolean or null Isolation forest outlier prediction; null when ml_score is null.
model_id string or null Hash id of training row ids + hyperparameters; null when no model was fit.
n_train_samples integer Number of prior snapshots used as training rows for the forest.
severity string "clean" or "material" (aligned with exit semantics). The schema allows "informational" for future use; current runs emit only clean or material.
exit_code integer Same convention as Exit codes above (0 or 2 on success path).
deterministic_diff array List of diff objects (see below).
diff_summary object Counts per diff kind (e.g. {"new": 1, "gone": 0}).
new_tcp_open boolean true if any diff row is a new TCP open port.
fail_on_diff_rule_triggered boolean true if --fail-on-diff-rule was set and a new TCP open port was present.

deterministic_diff[] entries

Each element describes one change vs the baseline (previous scan or pinned scan_id):

Field Type Description
kind string "new" (new open port), "gone" (was open, no longer open), or "service_drift" (same open port, service identity changed).
proto string e.g. "tcp".
port integer Port number.
before object or null Port row before change (null for new).
after object or null Port row after change (null for gone).
detail string Short human-readable reason.

When before / after are objects, they use the same keys as stored port rows: proto, port, state, service_name, product, version, extrainfo (with redaction applied to service fields before storage).

Example (truncated)

{
  "schema_version": "1.0",
  "scan_id": "",
  "target_key": "203.0.113.10",
  "profile_id": "",
  "profile_extra_args": "-p 22,80 -sV",
  "wall_time_utc": "2026-04-28T12:00:00+00:00",
  "nmap_version": "7.94",
  "ml_score": null,
  "ml_is_outlier": null,
  "model_id": null,
  "n_train_samples": 0,
  "severity": "clean",
  "exit_code": 0,
  "deterministic_diff": [],
  "diff_summary": {},
  "new_tcp_open": false,
  "fail_on_diff_rule_triggered": false
}

Changelog

See CHANGELOG.md.

License

This project is distributed under the MIT License.

About

Single-target nmap scan history, diff, and isolation-forest anomaly scoring.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages