Cataract: Tiered Web Enumeration

Table of Contents
Repo: github.com/YusufAlMahmeed/cataract . Star it and keep an eye on the GitHub page for updates. Bug reports, feature ideas, and suggestions are welcome: open an issue on the repo.
Cataract is actively maintained, so this page describes how it works rather than any one release. For the current flags, defaults, and release history, the repository and its changelog are always the source of truth.
What it is#
Cataract is a small Bash tool for authorized web penetration testing. Its one-liner:
Tiered, recursive, multi-target web enumeration for authorized web penetration testing.
It automates the tedious part of content discovery, deciding which wordlist, when, by cascading through escalating tiers of wordlists with feroxbuster while an nmap full-port scan runs in the background. The name is the idea: results fall through tiers like water down a cataract.
Why#
On a typical web engagement you start with a small wordlist, then reach for a bigger one, then a bigger one still, restarting the scan each time and juggling nmap on the side. Cataract turns that manual escalation into one flow: it runs a tier, pauses so you can decide whether the next (larger) tier is worth it, and keeps nmap and per-target logging organized while you work.
The tiers#
The cascade climbs from quick-and-common to broad-and-thorough:
dirb/common.txtdirb/big.txt- SecLists
raft-medium-directories.txt - SecLists
raft-large-directories.txt
Tiers 3 and 4 use the directories lists, not the files lists: directory
words carry no extension, so appending your extension set is correct instead of
producing waste like index.php.php, and directories are what recursion
descends into. When the matching raft-*-files.txt list is present, Cataract
also runs it as a filename pass without extensions, so real filenames are
still covered.
After each tier Cataract prompts before continuing, so you spend big wordlists
only where they earn their keep. You can also skip the cascade entirely and
supply your own wordlists with -w (see below).
Options#
Every setting is a flag, and the important ones have sensible defaults, so interactive mode needs none of them:
| Flag | What it does | Default |
|---|---|---|
-o <dir> | Output directory (required in non-interactive -a mode) | — |
-f <file> | Read targets from a file, one per line | — |
-t <n> | feroxbuster threads (how many requests run at once, not a time limit) | 50 |
-d <n> | Recursion depth: how many directory levels deep to keep descending | 2 |
-x <exts> | Comma-separated file extensions to append to each word | php,html,txt,js,json,bak,zip |
--no-ext | Don’t append any extensions on any pass | off |
-w <wordlist> | Use a custom wordlist instead of the tier cascade; repeatable, and run in the order given | — |
--dry-run | Print the plan and per-tier request estimates, then exit without scanning | off |
-k, --insecure | Skip TLS certificate validation (for self-signed lab certs) | auto-on for https:// |
-a, --auto | Non-interactive: run every tier and auto-enumerate discovered ports | off |
-H <header> | Add an extra HTTP header; repeatable (e.g. a session cookie) | — |
--rate-limit <n> | Cap feroxbuster at n requests per second | off |
--udp | Also sweep the top 100 UDP ports in the background (needs root) | off |
-h, --help | Print usage and exit | — |
By default Cataract runs the port scan in two phases: a fast full-port sweep
to find open ports quickly, then a deeper service- and script-detection scan on
just those ports. The fast sweep uses nmap by default (the accuracy-first
choice); set FAST_SCANNER=rustscan to use
RustScan
for much faster sweeps on
low-latency or lab networks (it can miss ports on high-latency or rate-limited
links), or FAST_SCANNER=auto to pick RustScan when it’s installed. Either way
the scan reports progress at an interval, so a long sweep never looks hung. Run it
(or at least the scan) as root for a SYN sweep, a “half-open” scan that never
finishes the TCP handshake, so it is quicker and quieter; without root it falls
back to a slower TCP connect scan and Cataract warns you at startup. Add --udp
to also sweep the top UDP ports alongside the TCP scan.
Features#
- Flexible target input: a bare IP,
host:port, or a full URL (bare values default tohttp://) - Per-target service and port selection in interactive mode
- Parallel full-port nmap scan in the background while feroxbuster works
- Four-tier wordlist cascade with a continue-prompt after each tier
- Auto-discovery of additional web ports nmap turns up, with the option to scan them too
- Recursive directory discovery, with configurable depth
- Automatic
-kfor HTTPS targets so self-signed certificates don’t break the run - Colorised output kept on screen while logging to a file and to JSON
- A per-target
summary.mdplus a combinedindex.mdreport - Scriptable via CLI flags for unattended runs
- tmux tabbed interface (one tab per target) that works over SSH and survives disconnects, with a sequential fallback when tmux isn’t available
- Preflight checks for the required tools and wordlists, with install hints
Install#
git clone https://github.com/YusufAlMahmeed/cataract.git
cd cataract && chmod +x cataract.shDependencies (Debian/Kali):
sudo apt update && sudo apt install -y nmap feroxbuster tmux jq dirb seclists bsdutils util-linux- Required: bash, nmap, feroxbuster,
script(util-linux), dirb wordlists - Recommended: tmux, jq
- Optional: SecLists (for the medium/large tiers)
Linux only (Kali/Debian/Ubuntu tested). Cataract uses util-linux
script to keep feroxbuster colorized while logging, which isn’t available
on macOS/BSD, so it exits early with a clear message on non-Linux hosts.
Usage#
Interactive mode walks you through targets and options:
./cataract.shYou can also pass targets directly, as bare IPs, host:port, or full URLs:
./cataract.sh -o results/ 10.10.10.10 10.10.10.20:8080 https://app.localWhat this does: -o results/ sets the output directory, and the remaining
arguments are the targets (a bare IP defaults to http://). To read many targets
from a file instead, use -f targets.txt.
For an unattended, authenticated, rate-limited run:
./cataract.sh -o results/ -a -t 30 -d 2 --rate-limit 40 \
-H 'Cookie: session=abc123' https://app.local:8443What this does: -a runs non-interactively through every tier (no
continue-prompts), -t 30 sets feroxbuster to 30 concurrent threads (concurrency,
not a 30-minute limit), -d 2 keeps recursion two directory levels deep,
--rate-limit 40 caps feroxbuster at 40 requests per second (gentler on a fragile
target), and -H 'Cookie: session=abc123' sends that session cookie on every
request so the scan runs as a logged-in user.
To skip the tier cascade and run your own wordlists in order, and preview the plan before committing to it:
./cataract.sh -o results/ -w quick.txt -w big.txt --dry-run https://app.localWhat this does: each -w adds a wordlist (they run in the order given),
--dry-run prints the plan and per-tier request estimates and then exits without
scanning, so you can see what a run will cost first.
See it run#
A quick run from start to finish: the interactive service/port prompts, the wordlist check, and the tiered feroxbuster scan with nmap working in the background.

A note on scope#
Cataract is built for authorized testing only, engagements where you have explicit permission to enumerate the target. Point it at your own labs, or at systems you are contracted to assess. Large wordlists against a host you don’t own is noisy, and out of scope.
Stay in the loop#
This tool is actively maintained. Watch the GitHub repository for updates, and if you hit a bug or have a suggestion, please open an issue , feedback is what drives the next tier.
Related posts#
- Shakabrah — an OffSec machine walkthrough where I use Cataract for the initial web enumeration.