Fast directory discovery (dirb/ffuf-style) written in Zig 0.16.
Status: basic implementation (MVP).
Reads a wordlist line-by-line and performs parallel HTTP checks for paths. Outputs NDJSON (one JSON object per line).
- Worker pool with parallel requests (
--concurrency, default 32) - Wordlist from file (
--wordlist) or fromstdin - Automatic
/insertion between base URL and word (words in the list should be without a leading slash) - NDJSON output with:
url,method,status,bytes,duration_ms, and more - Cross-platform (Windows / macOS / Linux), targeting Zig 0.16
Note:
https://example.comis reserved for documentation/demos; most paths correctly return 404. Use a real target for practical runs.
- Zig 0.16.0 (or newer in the 0.16 series)
This project uses Zig’s new I/O (0.16): std.http.Client.fetch with response_writer, in-memory buffering via std.Io.Writer.Allocating, and @memcpy instead of the removed `std.mem.copy .
zig buildUsing the build step:
zig build run -- dir --url https://example.com --wordlist ./words.txt
Or run the binary directly:
# Unix
./zig-out/bin/zigbuster dir --url https://example.com --wordlist ./words.txt
# Windows (PowerShell)
.\zig-out\bin\zigbuster.exe dir --url https://example.com --wordlist .\words.txtRead words from stdin:
cat words.txt | ./zig-out/bin/zigbuster dir --url https://example.com- --url — base URL (including scheme)
- --wordlist — path to wordlist (if omitted, reads from stdin)
- --output — write NDJSON to file (default: stdout)
- --concurrency — number of workers (default: 32)
- --timeout — per-request timeout in milliseconds (default: 5000)
{"url":"https://example.com/images","method":"GET","status":404,"bytes":1256,"words":0,"lines":0,"source":"dir","depth":0,"duration_ms":1280}Each line is a standalone JSON object (easy to pipe into jq, ship to ELK, etc.)
-
Worker pool + queue (Mutex + Condition Variable)
-
One std.http.Client per worker (lifetime spans multiple requests); per-iteration arena for temporary buffers (URL, response body) so destructors run in a safe order
-
Zig 0.16 I/O:
std.http.Client.fetch with response_writer to stream into a writer
std.Io.Writer.Allocating to capture response bytes in memory
-
Slice copy uses @memcpy (since std.mem.copy was removed/deprecated and @memcpy is the recommended replacement)
-
--filter-404: baseline request, then ignore “known 404” by matching status/length
-
Filters: --status-include/--status-exclude, --len-min/--len-max
-
HEAD probes where Content-Length is reliable
-
Rate limiting / jitter, progress and counters
-
Recursive mode (follow 200/301 discoveries), file suffix enumeration (-e php,html,json)
-
Extra fields: content_length, location, maybe title