ExploitSynth scanner CLI — AI port-identification from your terminal
Project description
ExploitSynth CLI
AI port identification from your terminal — for the open ports your scanner (nmap, Nessus) couldn't fingerprint. The CLI talks to the same engine as scan.exploitsynth.com; your scans, projects, and credits are shared.
Install
pipx install exploitsynth # isolated, on your PATH
Optional tab-completion for your shell:
exploitsynth --install-completion # bash | zsh | fish | powershell
Authenticate
Grab an API key from Settings → API keys in the web app, then:
exploitsynth login # prompts for the key, verifies, stores it
The key lives in ~/.config/exploitsynth/config.json (chmod 600). You can also
skip the file and export it per-shell:
export EXPLOITSYNTH_API_KEY=sk_...
Scan
# Known-open ports — identify them directly
exploitsynth scan 45.33.32.156 --ports 22,80,9929
# Discovery — find open ports first, then identify
exploitsynth scan 10.0.0.0/28 --scope top1000
# Import — feed the ports your scanner left unidentified
exploitsynth scan --nessus engagement.nessus --project acme
exploitsynth scan --nmap recon.xml --project acme
Chain it after your scanner
exploitsynth reads targets from stdin (-) or a file (-iL), so it drops
straight into a recon pipeline — point a fast scanner at the network, then let
ExploitSynth identify what it couldn't:
# pipe targets in
rustscan -a 10.0.0.5 --ports-only | exploitsynth scan - --ports 22,80,9929
# or a host list
exploitsynth scan -iL hosts.txt --scope top100
Live per-port progress streams into your terminal, with the same per-port timeout countdown you see in the web app. Each scan costs 1 credit per port; the cost is previewed (and confirmed in an interactive shell) before it runs.
Scan a private network (--via local)
Targets on an internal network (10.x, 192.168.x) or behind a firewall that
only allows your source IP aren't reachable from the cloud. --via local solves
this: discovery runs on your machine, and a reverse tunnel routes the engine's
probes back out through your machine — so the scan reaches anything you can
reach. Typical HTB / internal-pentest flow:
# 1. get on the network (client VPN, on-site LAN, HTB, …)
sudo openvpn engagement.ovpn # you can now reach 10.129.45.12
# 2. one command
exploitsynth scan 10.129.45.12 --via local --scope top1000
What happens: local nmap finds the open ports, the CLI opens an outbound tunnel
(no inbound ports needed), and the cloud identifies each service through that
tunnel. The agent, prompts, and LLM stay in the cloud — only network egress is
borrowed from your box.
Requirements & notes:
- You must be on a network that can reach the target (the CLI says so if you're not).
nmapmust be installed;chiselis fetched automatically if it isn't on PATH.- The tunnel only lives while the command runs, so
--via localstreams live and can't be combined with--no-follow. Ctrl-C tears the tunnel down. - Cost is the number of open ports found (discovery is free — it's your nmap).
Options
| Flag | Meaning |
|---|---|
--ports 22,80,9929 |
Known-open ports to identify directly (skips discovery) |
--scope top100|top1000|all |
Discovery scope (or a range like 1-1000) |
--via local |
Scan a private/firewalled target through a tunnel out of this machine |
-iL FILE |
Read newline/comma-separated targets from a file |
- (as TARGET) |
Read targets from stdin |
--nessus FILE / --nmap FILE |
Import unidentified ports from a scan export |
--project NAME |
Engagement to file the scan under (created if missing) |
--label TEXT |
Optional scan label |
--timeout 300 |
Per-port agent budget in seconds (30–600) |
--slow |
Run one agent at a time instead of three |
--no-follow |
Fire-and-forget; don't stream progress |
--yes |
Skip the credit-cost confirmation |
--json |
Emit machine-readable JSON on stdout |
Inspect
exploitsynth scans # recent scans
exploitsynth scans --project acme
exploitsynth show <scan_id> # full result table
exploitsynth show <scan_id> --reasoning # include the agent's reasoning
exploitsynth credits # your credit balance
exploitsynth cancel <scan_id> # cancel a queued/running scan
Scripting
Every read command supports --json (printed to stdout; progress and notes go to
stderr, so pipes stay clean):
exploitsynth scans --json | jq '.[] | {id, status}'
exploitsynth show <scan_id> --json | jq '.results[] | {port, service, version}'
Exit codes: 0 success, 1 error, 3 insufficient credits.
Self-hosting
Point the CLI at your own deployment:
exploitsynth login --url https://scan.example.com
# or
export EXPLOITSYNTH_API_URL=https://scan.example.com
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file exploitsynth-0.3.2.tar.gz.
File metadata
- Download URL: exploitsynth-0.3.2.tar.gz
- Upload date:
- Size: 17.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
10dc0ad84073774f688f920bfd972c554ae46e007f2d9b2a6cd09b148b09a879
|
|
| MD5 |
2e12d348723a22948e9983cd4b2a1897
|
|
| BLAKE2b-256 |
e5802a8aa05312175ce3d08cc109b260f43907a8557b90954fbb1654d6435760
|
File details
Details for the file exploitsynth-0.3.2-py3-none-any.whl.
File metadata
- Download URL: exploitsynth-0.3.2-py3-none-any.whl
- Upload date:
- Size: 23.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d48a0b15133d328391bececcc6b0ba8d579236f68ab4e0d470aea299dddb43a8
|
|
| MD5 |
f2614b797a37c07913f473b80b927f04
|
|
| BLAKE2b-256 |
f245dcefc4a45d48dce919270cbf525805a997ef79620eaab7eec8b726a5d7a2
|