A cross-platform domain reconnaissance wrapper. Point it at a host (or a list of hosts) and it runs DNS, HTTP fingerprinting, WAF/CDN detection, TLS inspection, port scanning and template-based vulnerability scanning in one command, producing a readable Markdown report plus machine-readable CSVs.
easm-recon does not scan anything itself. It orchestrates mature open-source tools into one consistent, bounded, fail-safe workflow, so you get repeatable results without wiring eight tools together by hand.
- Orchestrates: dnsx, httpx, wafw00f, tlsx, cdncheck, nmap, nuclei, subfinder
- Runs on: Windows, Linux and macOS (pure-Python orchestrator, no shell glue)
- Two modes: single host, or a parallel batch from a list file
- Light by default (active, but low-volume): only DNS + cdncheck are truly passive; httpx/tlsx/wafw00f touch the target but send little. The noisy stages (ports, nuclei) are strictly opt-in — and
--dry-runestimates the footprint first. - Customizable: per-tool flags, presets, and a config file (see Customization)
Scope. This is a reconnaissance and automated-scanning tool (EASM). It is not a web-pentest tool: it performs no authenticated testing, manual exploitation or fuzzing. Every external tool it drives is open-source and downloaded from its official release at install time; nothing is bundled.
- Python 3.8+ is the only hard dependency. The installer builds an isolated venv for everything else.
- Internet access for the installer (it downloads tool binaries from official GitHub releases and verifies each against its published SHA-256 checksum).
- nmap is optional and installed separately (see below). Without it, port scans fall back to naabu, then to a built-in Python connect-scan.
git clone https://github.com/Lockbearer/easm-recon.git
cd easm-recon
python install.py # OS/arch-detected binaries (SHA-256 verified) + venv + wafw00f
python install.py --templates # optionally also pull nuclei templatesinstall.py detects your platform, fetches the matching binaries into ./bin,
and creates the isolated venv used for wafw00f. nmap, if you want richer port
scans, is installed with your platform's package manager:
# Windows
winget install Insecure.Nmap
# Debian / Ubuntu
sudo apt install nmap
# macOS
brew install nmappython -m easm example.com # single host, light (see note below)
python -m easm example.com --dry-run # estimate traffic, scan nothing
python -m easm example.com --full # + ports + nuclei + subdomains
python -m easm targets.txt --full --concurrency 6 # batch, 6 hosts in parallelThe target is treated as a list file if a file by that name exists on disk, otherwise as a single host.
What "light" means (important). Active (touches the target) and noisy (high volume) are two different axes. With no flags the run is active but low-volume:
- Passive — only dnsx (DNS to a resolver) and cdncheck (IP-range lookup) never touch the target.
- Active, low-volume — httpx and tlsx make a handful of real HTTP/TLS requests; WAF detection (wafw00f, or the built-in behavioural fallback) sends a small battery of attack-pattern probes (SQLi/XSS test payloads) to see what gets blocked. It's a bounded set of requests — not a flood — but it is traffic to the target and can appear in a WAF/IPS log.
- Noisy — only the opt-in
--ports(especially-p-) and--nucleigenerate heavy traffic (thousands of requests / tens of thousands of packets).
Run --dry-run to see the estimated footprint before you scan, and only test
hosts you are authorized to.
Optional launcher, so you can type easm <host> from anywhere:
# Linux / macOS
ln -s "$(pwd)/easm.sh" ~/.local/bin/easm
easm example.com --full
# Windows: add this folder to PATH and use easm.bat -> easm example.com| Flag | Default | Mode | What it does |
|---|---|---|---|
target |
required | both | a host or a path to a list file |
--ports |
off | both | port scan: nmap, else naabu, else Python connect-scan. Active |
--nuclei |
off | both | nuclei vulnerability/exposure scan. Active |
--subs |
off | both | subdomain discovery (subfinder) |
--full |
off | both | shorthand for --ports --nuclei --subs |
--dry-run |
off | both | print an estimate of the network footprint (requests/packets) and exit — sends nothing |
--concurrency N |
4 | batch | number of hosts scanned in parallel |
--nuclei-timeout N |
900 | both | nuclei wall-clock cap in seconds; if hit, results are flagged partial |
--profile NAME |
default |
both | flag preset: default / fast / deep (see Customization) |
--<tool>-args "..." |
none | both | append extra flags to one tool, e.g. --nmap-args "-p-" (see Customization) |
The underlying tools are highly configurable, so easm-recon exposes their flags at four layers, each overriding the previous:
built-in default -> config.json -> --profile -> --<tool>-args
Only tunable flags are ever exposed. The I/O flags that results are parsed from
(the target, -json/-jsonl, -o <file>) are always added by the engine and
cannot be overridden, so customization can never break report parsing.
1. Pass-through flags for a one-off run:
python -m easm example.com --ports --nmap-args "-p- -A" # all ports + OS/version
python -m easm example.com --nuclei --nuclei-args "-tags cve" # CVE templates only
python -m easm example.com --subs --subfinder-args "-all" # all subfinder sourcesAvailable for every tool: --dnsx-args, --httpx-args, --tlsx-args,
--cdncheck-args, --nmap-args, --naabu-args, --nuclei-args,
--subfinder-args. Values are tokenized and passed as an argument list, never a
shell string, so a target can never be interpreted as a command.
2. Profiles via --profile:
| Profile | nmap | nuclei |
|---|---|---|
default |
top-1000 ports, --version-light, 4m cap |
low -> critical |
fast |
top-100 ports, 2m cap | high/critical, tags cve,exposure,misconfig |
deep |
all ports -p-, -sC, --version-all, 10m cap |
info -> critical, 2 retries |
python -m easm example.com --profile deep --fullThe nmap subprocess cap auto-adjusts to the profile's --host-timeout, so a
deep scan is never cut off prematurely.
3. config.json for persistent defaults and your own named profiles, with no
code editing. Copy config.example.json to config.json
(in the repo root, or ~/.easm/config.json) and edit. config.json is
git-ignored; the .example template is tracked.
Single host -> output/<host>/<timestamp>/: a report.md plus the raw
*.jsonl from each tool.
Batch -> output/_batch/<timestamp>/:
| File | Contents |
|---|---|
report.md |
summary table followed by every host's full report |
summary.csv |
one row per host: ip, status, server, waf, tls, ports, vuln/subdomain counts |
nuclei.csv |
one row per finding: host, severity, name, template, matched_at |
subdomains.csv |
host, subdomain |
ports.csv |
host, port, service, version |
_manifest.tsv |
host to its exact output directory (traceability) |
Per host, the pipeline is:
dnsx -> cdncheck -> httpx -> wafw00f -> tlsx -> [nmap] -> [nuclei] -> [subfinder] -> report
Bracketed stages are the opt-in active ones. The design goals:
- Graceful degradation. If a tool is missing or blocked, its stage is skipped or a built-in Python fallback runs (nmap -> naabu -> Python connect-scan; wafw00f -> behavioural probe; dnsx/httpx/tlsx -> stdlib). One tool failing never stops the scan.
- Bounded. Every external tool is time-capped (nmap
--host-timeout, a nuclei watchdog, per-subprocess wall-clock limits). Nothing hangs forever. - Injection-safe. Tools are invoked with argument lists, never shell strings, so a hostname can never be interpreted as a command.
- Deterministic batches. Each host writes to its own directory and the
aggregator reads exactly those directories (recorded in
_manifest.tsv). It never guesses a "latest" folder. - No silent truncation. If nuclei is cut off by its timeout, the report and
CSV mark it (
*) as partial, so a partial scan is never mistaken for a complete one. - Environment isolation. wafw00f runs from its own venv, and
PYTHONHOME/PYTHONPATHare cleared before Python is invoked, so a messy host environment cannot break it.
A tool binary is blocked by antivirus or Windows Smart App Control. The
orchestrated tools are unsigned binaries from official GitHub releases, and
Windows Smart App Control or some antivirus products may block one (you will see
WinError 4556 / "an Application Control policy blocked this file"). easm-recon
records this as an ERROR and the report says the stage did NOT run - it
is never silently reported as a clean "0 findings". Options, most-preferred
first:
- Run on Linux, macOS, or WSL, where this restriction does not apply. The orchestrator behaves identically on every platform.
- Add the
bin/folder to your antivirus exclusions (classic Defender AV). - Build the tool from source with Go (e.g.
go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest) so the binary is locally compiled.
Smart App Control is a Windows security feature; change it only if you fully understand the implications.
--ports and --nuclei are active and noisy. Only run them against systems
you own or are explicitly authorized to test (for example scanme.nmap.org,
example.com, or your own assets). Unauthorized scanning is illegal in many
jurisdictions. If you are scanning corporate infrastructure, notify your SOC
first. You are solely responsible for how this tool is used.
MIT. See LICENSE.
Built on the work of ProjectDiscovery (httpx, nuclei, dnsx, naabu, cdncheck, tlsx, subfinder), wafw00f and nmap.
easm-recon only orchestrates these tools. Their binaries are downloaded from official sources at install time and are not bundled in this repository.