v5: -brute flag and bruteforce.wordlists config are accepted but never used
Hi @caffix, thanks for all the work on v5 and the project in general. The rewrite has been great to explore, and I've been using it in a project where the new engine model has already paid off for us. Opening this as a question rather than a PR because I'm not sure whether what I'm seeing is an intentional change or a loose end, and I'd rather ask before writing code that turns out to be unwanted.
What I observed
In v5.1.1 (and on develop), the -brute CLI flag and the bruteforce.wordlists YAML key are still parsed, and the wordlist is loaded into config.Config.Wordlist. Nothing in engine/ reads that field, so the wordlist sits in memory and then goes unused. The only plugin under engine/plugins/brute/ is alterations.go, which consumes c.AltWordlist, not c.Wordlist. FQDN-Alterations even gates on cfg.BruteForcing && cfg.Alterations, which reuses the brute toggle to mean "also do alterations", so enabling -brute visibly does something — just not what a v4 user would expect.
Concretely:
config/brute.gopopulatesc.Wordlistinternal/enum/cli.go:451setsconf.Wordlist = e.BruteWordList.Slice()git grep '\.Wordlist' engine/returns nothing
From a user's point of view, amass enum -brute -w wordlist.txt example.com runs cleanly and produces no dictionary guesses of <word>.example.com. A v4 user would assume it did.
Why I'm asking
I couldn't find anything in the v5.0.0 release notes, the CHANGELOG, or issues/discussions that called out the removal. Other removals (subs/emails subcommands, the embedded collection engine, syslogd) are listed explicitly, so the omission feels more like an unfinished port than a deliberate excision — but I'd rather hear it from you than guess.
So the question is really: was wordlist brute force dropped from v5 on purpose, or is a Go port of resources/scripts/brute/bruteforcing.ads still on the roadmap?
If intentional, no objection from me — but in that case it'd probably be worth removing c.Wordlist and -w/-brute (or logging a clear warning) so users aren't silently getting less than they asked for.
Concrete suggestion, if a port is welcome
I'd be happy to contribute a PR if you're open to it. Rough shape I had in mind:
- New file
engine/plugins/brute/bruteforcing.goregistering an FQDN handler at a priority afterDNS-IPso we only generate guesses for names whose resolution status we already know. - Gate on
cfg.BruteForcing, scope membership, and a TTL check viasupport.TTLStartTime+AssetMonitoredWithinTTL(mirroring howFQDN-Alterationsavoids replays). - Skip CNAMEs and names without A/AAAA, matching the v4 script's
has_cname/has_addrguards — this keeps noise down. - Emit guesses through
support.StoreFQDNsWithSource/ProcessFQDNsWithSourceso downstream DNS resolution drops synthetic names that don't resolve, and the ones that do flow naturally throughDNS-IP,DNS-Subdomains,DNS-Apex. - Optional recursion behind the existing v4 knobs (
recursive,min_for_recursive,max_depth) so depth stays bounded on large zones.
The scope decisions I'd want your steer on:
- Rate limiting: should the plugin lean on the resolver pool's existing concurrency, or carry its own semaphore the way some v4 scripts did?
- Recursion default: v4 defaulted to off and required
min_for_recursive. I'd keep that unless you prefer a stricter stance. - Ethics/footprint: the wordlist is network active by nature. Happy to add a prominent
Activecheck and a log line on startup so users can't miss that they're generating live queries.
If you'd rather I open a smaller "document the limitation" PR that renames or gates the config keys, I can do that instead.
Either way, thanks again for the project and for maintaining it. Happy to adjust scope based on whatever direction you'd prefer.
Source: owasp-amass/amass