Single domain reconnaissance. Point it at one domain and it maps the attack surface (subdomains, infrastructure, open ports, tech stack, endpoints, files, secrets), saves one JSON file per scan, and serves a local dashboard with a graph view.
Only scan targets you are authorized to test.
Linux with systemd and Python 3.10 or newer.
cd argus-recon
./install.shThis installs the dependencies, asks you to create the administrator account,
registers the argus-recon systemd user service, and starts the dashboard on
http://127.0.0.1:7666. It is safe to run again at any time. Use
./install.sh --upgrade to update and restart.
Open http://127.0.0.1:7666, sign in, type a domain, press Run scan. The scan
runs in the background with a live log and opens in the graph view when it
finishes. Results are saved to scans/.
The dashboard is not open. Once key.json exists (the installer creates it),
every page and every API route needs a signed session, including from
localhost.
- Administrator · created at install time. Sees every scan, manages
accounts, reads the access history. Admin area:
/recon/admin. - Operator · created by an administrator. Sees only their own scans, and only gets the scan options the administrator enabled for them.
Accounts live in key.json next to the code: passwords as PBKDF2-SHA256
hashes (never plaintext), each account's allowance, and the secret that signs
session tokens. The file is written 0600 and is gitignored. Sessions are
HS256 JWTs in an httpOnly, SameSite=Lax cookie; state-changing requests also
have to echo a CSRF value carried inside the token. Changing a password
invalidates every session already issued for that account.
./install.sh --admin create the administrator (turns authentication on)
./install.sh --check among other things, reports whether auth is configuredLost the admin password? Delete key.json and run ./install.sh --admin.
That resets accounts only; scans are untouched.
| Setting | Effect |
|---|---|
| Scans per day | Refused past this many starts in a UTC day. 0 = unlimited |
| Scans at once | How many of their scans may run concurrently. 0 = unlimited |
| See every account's scans | Off: the library and every scan URL show only their own runs |
| Delete scans | Whether they may remove a scan from the library |
| Port scan / Tor / web archive / deep DNS | Whether each option is available to them at all |
Argus is an orchestrator. These are the external tools it drives, and when. Findings are tagged in the UI with a short source code instead of a tool name, so an exported scan does not disclose the toolchain; the mapping is here.
| Tool | Code | Stage | What it does | If missing |
|---|---|---|---|---|
| subfinder | n |
1 · subdomains | Fast passive name enumeration, the first pass | crt.sh + DNS brute cover it |
| bbot | b |
1 · subdomains | The deep passive sweep behind subfinder | quick pass only, fewer hosts |
| crt.sh | c |
1 · subdomains | Certificate transparency logs | skipped |
| SecurityTrails | s |
1 · subdomains + DNS | Deep DNS: larger host set, full current DNS, historical DNS | option locked (needs a key) |
| dnsx | r |
1 · resolve | Bulk resolution of every candidate host | slower Python resolver |
| httpx | h |
2 · probe | Mass HTTP probe: which hosts are live, on which scheme | each stage probes for itself, slower |
| nmap | p |
2a · port scan | Aggressive service/version, OS guess, default scripts, traceroute, aimed at the discovered open ports | port-scan toggle stays locked |
| naabu / masscan | p |
2a · port scan | Fast full-range discovery, so nmap version-scans every open port, not just the top 1000 | nmap connect sweep does the discovery |
| cdncheck | p |
2a · port scan | Flags CDN/WAF/cloud edge IPs so their ports read as the edge's, not the origin's | header-based edge detection in the HTTP review |
| WhatWeb | W |
2a + 3 · fingerprint | Tech stack per host, and per non-standard web port | no tech tags |
| waybackurls | y |
2b · web archive | URLs the domain used to serve, from the internet archive | the archive's CDX index over HTTP is used instead |
| katana | k |
4 · deep crawl | JS-aware discovery: bundled routes, lazy chunks, runtime XHR targets | built-in crawler runs alone |
| built-in crawler | crawler |
5 · crawl | Fetches bodies, extracts forms and fields, maps buttons to requests | — |
| built-in JS parser | js |
5 · crawl | Deep asset read: endpoints, secrets, GraphQL / WebSocket / OAuth, source maps, cloud refs (AWS / Azure / GCP / Firebase), internal IPs, analytics IDs, TODO / FIXME, parameters | — |
| built-in HTTP review | H |
3b · http review | Security headers, cookies, CORS, methods (TRACE / OPTIONS), server fingerprint, CDN / WAF from headers | — |
| wafw00f | H |
3b · http review | Names the WAF in front of a host | header signatures still detect common edges |
| built-in TLS review | T |
3b · tls review | TLS versions, cipher, full certificate (issuer / SAN / expiry), weak-protocol probe | — |
| built-in bypass probe + nomore403 | x |
6b · bypass | Replays 401 / 403 with 60+ path / header / method tricks (the iamj0ker/bypass-403 "Joker" and nomore403 catalogues) to find front-door-only access control | native catalogue runs with no external tool |
| arjun | A |
6c · params | Hidden query / body parameter discovery on the interesting endpoints | JS-extracted parameters only |
| dalfox | X |
6d · XSS (toggle) | Reflected / stored / DOM XSS across every user-controlled channel · URL query, form and JSON bodies, and the Cookie header. Findings carry the payload and a replayable request | XSS toggle stays off |
| sqlmap | Q |
6e · SQLi (toggle) | SQL injection across every user-controlled channel · URL query, form and JSON bodies, the Cookie header, and (via level) User-Agent / Referer. Every technique · endpoint / param / payload / DBMS | SQLi toggle stays off |
| ffuf or feroxbuster | f |
6 · bruteforce | Content discovery against a calibrated per-host baseline | no bruteforce stage |
| ipinfo.io | i |
7 · enrich | Provider, ASN, country, hosting-or-not per IP | IPs stay bare |
| Shodan / InternetDB | S |
2a · port scan (+ passive) | Known open ports, services, versions, CVEs and TLS / org / ASN / geo, merged into the port scan's own results (also the passive-scan intel path). Key set in the admin panel | InternetDB (free, no key) when there is no Shodan key |
| nuclei | N |
9 · nuclei (toggle) | Template scan with a selection derived from the detected stack (technologies / ports / services), not every template | Nuclei toggle stays off |
| tor + torsocks | — | 0 · transport | Routes the entire scan through Tor · every request, DNS lookup, and external tool (sqlmap, dalfox, nuclei get the SOCKS proxy natively). Detects a target rejecting Tor exit nodes and raises a popup | Tor toggle stays locked |
| kuzu (or Neo4j) | — | 10 · graph | Stores the scan graph for querying | graph still renders from the JSON |
./install.sh installs all of these. ./install.sh --check reports which are
present and what degrades without each.
Everything below is on the launcher at the top of the dashboard. The toggles are in the bar; the rest are behind Options.
| Toggle | Default | What it does |
|---|---|---|
| deep DNS | off | Larger subdomain set, full current DNS records, and historical DNS (previous IPs, name servers, MX, with dates). Needs an API key. If the key's monthly allowance is spent, the launcher says so before the scan starts and offers: run without it, or paste another key |
| passive | off | Passive enumeration only. Nothing is sent to the target, and passive host intelligence (Shodan with a key, else the free InternetDB) is folded into the results. Rules out the port scan and the active HTTP/TLS/bypass reviews |
| via Tor | off | Routes every request, name lookup and external tool through Tor · the active scanners (sqlmap, dalfox, nuclei) are handed the SOCKS proxy natively, and sqlmap re-checks the circuit so a broken proxy aborts the tool instead of leaking. If a circuit cannot be established the scan aborts rather than falling back to a direct connection. If the target is rejecting Tor exit nodes, the dashboard says so in a popup |
| port scan | off | Scans every discovered IP for open ports and services, fingerprints each open web port, and hands non-standard web ports (:8080, :8443) to the crawler as seeds. Folds in Shodan's known ports / services / CVEs for each IP. Slow, and it touches infrastructure directly |
| web archive | off | Mines the internet archive for URLs this domain used to serve: retired admin panels, old API versions, files published then deleted. Sends nothing to the target. What it finds is re-checked by the crawler |
| XSS test | off | Tests every user-controlled channel · URL query, form and JSON bodies, and the Cookie header · for reflected / stored / DOM XSS (dalfox). Active · sends crafted requests to the target. Findings carry the type, parameter, the payload sent and a replayable request |
| SQLi test | off | Tests every user-controlled channel · URL query, form and JSON bodies, the Cookie header, and (via level) User-Agent / Referer · for SQL injection (sqlmap), every technique. Findings carry the endpoint, parameter, payload and back-end DBMS |
| Nuclei | off | Runs near the end with a template selection derived from the detected stack (technologies, ports, services), not every template. Each result is a finding |
| Scope | What counts as the target |
|---|---|
| Apex + subdomains (default) | A subdomain target pivots to its apex, so the whole estate is enumerated |
| Host + subdomains | The host is taken literally; its own subdomains are still enumerated |
| Single host | This host and nothing else. No subdomain enumeration; anything off-host is recorded but never followed |
| Setting | Default | Meaning |
|---|---|---|
| Max pages per host | 600 | Cap on pages the crawler fetches per host |
| Max depth | 6 | How far from a seed the crawler will follow links |
| skip passive-enum engine | off | Skip the deep sweep; use the quick pass + certificate transparency + DNS brute. No effect in single-host mode |
Every stage runs by default; switch one off to skip it.
| Stage | What you lose by skipping it |
|---|---|
subdomains |
Host enumeration. Only the target itself is resolved |
fingerprint |
Tech-stack tags on hosts and ports |
http_analysis |
The HTTP security review (headers, cookies, CORS, methods, CDN/WAF). Active scans only |
tls |
The TLS/certificate review (versions, ciphers, expiry, weak protocols). Active scans only |
crawl |
Endpoints, forms, fields, JS analysis, secrets · the bulk of a scan |
bruteforce |
Content discovery of unlinked paths and files |
bypass |
The 401/403 access-control bypass probe. Active scans only |
paramscan |
Hidden-parameter discovery (arjun). Active scans only |
ip_enrich |
Provider, ASN, country and hosting classification per IP |
shodan |
Shodan / InternetDB host intel (ports, services, CVEs) merged into the port scan's results · and the intel source for a passive scan |
classify |
Field-intent tagging (credentials, PII, tokens, IDOR, SSRF, …) |
graph |
The scan is not loaded into the graph database. The graph view still renders from the JSON |
Every stage feeds one ranked Findings list: each finding carries a severity, a confidence score, the raw and parsed evidence, its source, a plain-language risk and recommendation, and is deduplicated so the same issue seen by two tools becomes one entry.
The left panel is the estate; the graph is its shape; the table is every request. Each panel section has its own filter: subdomains by response code, infrastructure by announcing AS, tech stack by fingerprint, secrets by severity, discovered files by kind and by response code.
The graph shows at most 100 children of one type per parent. Beyond that a
+N more marker appears; clicking it opens the next hundred, and it retires
when the last batch has been loaded. Endpoint, request, field, JS and file
layers stay hidden until a single subdomain is selected · pick one from the
host filter or click it in the graph. Two renderers are available behind the
1 / 2 switch: the built-in canvas engine, and Cytoscape with the fCoSE
layout.
A large scan's graph is built in the background: the page shows "Building graph…" and picks it up when it is ready, however long that takes.
./argus status
./argus open open the dashboard
./argus start|stop|restart
./argus logs follow the service log
./argus upgrade pull the latest and restartSet in .env or the environment. Full list in modules/config.py.
| Variable | Default | Purpose |
|---|---|---|
SECURITYTRAILS_KEY |
none | deep DNS: more subdomains plus full and historical DNS |
IPINFO_TOKEN |
none | IP enrichment (provider, ASN, country) |
ARGUS_GRAPH_BACKEND |
auto |
graph store: auto, kuzu, neo4j, or none |
ARGUS_WEB_HOST / ARGUS_WEB_PORT |
127.0.0.1 / 7666 |
dashboard bind |
ARGUS_KEY_FILE |
./key.json |
account store location |
ARGUS_TOKEN_TTL |
43200 |
session lifetime in seconds |
ARGUS_ACCESS_LOG |
1 |
set 0 to disable the dashboard access log |
ARGUS_WAYBACK_MAX_URLS |
25000 |
ceiling on archived URLs ingested per scan |
ARGUS_GRAPH_VIEW_NODES |
6000 |
node budget for one graph response |
- This tool crawls and bruteforces actively. Get permission first.
- Missing optional tools degrade speed, not capability.
- A JSON access log of dashboard visitors is written under
scans/.access/, naming the account behind each request. The admin area reads it back. - Secrets in
.envand accounts inkey.jsonare gitignored and never leave the machine.