### Install Caddy for integration test Source: https://github.com/epi052/feroxbuster/blob/main/tests/policies/README.md Install the Caddy web server using either snap or apt package manager. Required for the Caddy-based auto-bail integration test. ```bash sudo snap install caddy # or sudo apt install caddy ``` -------------------------------- ### Install feroxbuster on Kali Linux via apt Source: https://github.com/epi052/feroxbuster/blob/main/README.md Preferred installation method for Kali Linux. Installs feroxbuster from the repositories, adds a ferox-config.toml in /etc/feroxbuster/, command completion for bash, fish, and zsh, and a man page entry. ```bash sudo apt update && sudo apt install -y feroxbuster ``` -------------------------------- ### Calling initialize from main (src/main.rs) Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md Example call to `scanner::initialize` with the wordlist length and cloned handles, awaited. ```rust // src/main.rs scanner::initialize(handles.wordlist.len(), handles.clone()).await?; ``` -------------------------------- ### Using Configuration::new() in main.rs Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/configuration.md Example usage of Configuration::new() from main.rs, wrapping the result in an Arc and adding error context. ```rust // used from main.rs let config = Arc::new(Configuration::new().with_context(|| "Could not create Configuration")?); ``` -------------------------------- ### Manual filter application example Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/filters.md Example of applying filters manually, as the filter handler does on `Command::AddFilter`. Creates a `FeroxFilters` instance, pushes a `SizeFilter` (content_length 5120) and a `StatusCodeFilter` (filter_code 404), then checks a default `FeroxResponse` against them. The `tx_stats` variable is a `CommandSender`; if the response is filtered, a debug log message is emitted. ```rust use feroxbuster::{ filters::{FeroxFilters, SizeFilter, StatusCodeFilter}, response::FeroxResponse, traits::FeroxFilter, }; use std::sync::Arc; let mut filters = FeroxFilters::default(); filters.push(Box::new(SizeFilter { content_length: 5120 })).unwrap(); filters.push(Box::new(StatusCodeFilter { filter_code: 404 })).unwrap(); let response = FeroxResponse::default(); let filtered = filters.should_filter_response(&response, tx_stats); // tx_stats: CommandSender if filtered { log::debug!("response would not be reported"); } ``` -------------------------------- ### Check cargo version Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Verifies that cargo is installed and shows its version. The output shown is an example of what you might see. ```shell script $> cargo --version cargo 1.45.0 (744bd1fbb 2020-06-15) ``` -------------------------------- ### Install feroxbuster on Windows x86_64 via PowerShell Source: https://github.com/epi052/feroxbuster/blob/main/README.md Downloads and extracts the Windows x86_64 feroxbuster release, then verifies the installation by running the executable with the -V flag. ```powershell Invoke-WebRequest https://github.com/epi052/feroxbuster/releases/latest/download/x86_64-windows-feroxbuster.exe.zip -OutFile feroxbuster.zip Expand-Archive .\feroxbuster.zip .\feroxbuster\feroxbuster.exe -V ``` -------------------------------- ### ClientConfig usage with initialize Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/client.md Example of constructing a `ClientConfig` and calling `client::initialize` with `--insecure`, `--server-certs`, and mTLS options. Uses a proxy, custom headers, and a scope for redirect handling. On success, the client is ready for requests; on failure, prints an error. ```rust use feroxbuster::{client, client::ClientConfig}; use std::collections::HashMap; use url::Url; let headers = HashMap::new(); let scope = vec![Url::parse("https://example.com").unwrap()]; let server_certs = vec!["/etc/ssl/private/rootCA.pem".to_string()]; let client_config = ClientConfig { timeout: 7, user_agent: "feroxbuster/2.13.1", redirects: true, insecure: true, headers: &headers, proxy: Some("http://127.0.0.1:8080"), server_certs: Some(server_certs), client_cert: Some("/path/client.crt"), client_key: Some("/path/client.key"), scope: &scope, }; match client::initialize(client_config) { Ok(client) => { /* use client.request(...) */ } Err(e) => eprintln!("client build failed: {e}"), } ``` -------------------------------- ### Using FeroxScanner::new in event handler (src/event_handlers/scans.rs) Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md Example of creating a scanner and spawning its `scan_url` task, then setting the task on the scan. ```rust // src/event_handlers/scans.rs (ScanHandler::ordered_scan_url) let scanner = FeroxScanner::new( &target, order, self.get_wordlist(0)?, self.limiter.clone(), self.handles.clone(), ); let task = tokio::spawn(async move { scanner.scan_url().await }); ferox_scan.set_task(task).await?; ``` -------------------------------- ### initialize function signature (src/scanner/init.rs) Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md Async function that performs one-time setup for scans, such as warming up the engine. Takes the number of words and shared handles, returns `Result<()>`. ```rust /// Perform steps necessary to run scans that only need to be performed once (warming up the /// engine, as it were) pub async fn initialize(num_words: usize, handles: Arc) -> Result<()> ``` -------------------------------- ### Install feroxbuster on Windows via Winget Source: https://github.com/epi052/feroxbuster/blob/main/README.md Installs feroxbuster on Windows using the Winget package manager. ```powershell winget install epi052.feroxbuster ``` -------------------------------- ### Install feroxbuster on Windows via Chocolatey Source: https://github.com/epi052/feroxbuster/blob/main/README.md Installs feroxbuster on Windows using the Chocolatey package manager. ```powershell choco install feroxbuster ``` -------------------------------- ### Run heuristics at scan start in FeroxScanner Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/heuristics.md Shows how FeroxScanner uses both heuristics at scan start. It creates a HeuristicTests instance, checks for directory listing and optionally extracts links, then detects 404-like responses and handles the result by stopping recursion or bumping the bar. ```rust let test = heuristics::HeuristicTests::new(self.handles.clone()); if let Ok(Some(dirlist_result)) = test.directory_listing(&self.target_url).await { // directory listing found: extract links, optionally stop recursion if self.handles.config.extract_links { let mut extractor = ExtractorBuilder::default() .response(&dirlist_result.response) .target(ExtractionTarget::DirectoryListing) .url(&self.target_url) .handles(self.handles.clone()) .build()?; let result = extractor.extract_from_dir_listing().await?; extraction_tasks.push(extractor.request_links(result).await?); } } let num_reqs_made = test.detect_404_like_responses(&self.target_url).await?; match num_reqs_made { Some(WildcardResult::WildcardDirectory(num_reqs)) => { /* stop recursion, bump bar */ } Some(WildcardResult::FourOhFourLike(num_reqs)) => { /* bump bar */ } _ => {} } ``` -------------------------------- ### Generate test coverage with grcov Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Installs grcov and sets up the environment to generate test coverage reports. It builds and tests the project, then generates an HTML coverage report and opens it in Firefox. ```sh cargo install grcov rustup component add llvm-tools rustup install nightly rustup default nightly export CARGO_INCREMENTAL=0 export RUSTFLAGS="-Cinstrument-coverage -Clink-dead-code -Ccodegen-units=1 -Coverflow-checks=off" export LLVM_PROFILE_FILE="target/debug/coverage/profraw/feroxbuster-%p-%m.profraw" export RUSTDOCFLAGS="-Cpanic=abort" rm -r target/debug/coverage/profraw cargo build cargo test grcov . --source-dir . --keep-only "src/*" --binary-path ./target/debug/ -t html --branch --ignore-not-existing -o ./target/debug/coverage/ firefox target/debug/coverage/index.html ``` -------------------------------- ### Install feroxbuster on macOS via Homebrew Source: https://github.com/epi052/feroxbuster/blob/main/README.md Installs feroxbuster via Homebrew on macOS. ```bash brew install feroxbuster ``` -------------------------------- ### Install rustup and update Rust Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Installs Rust via rustup and updates it to the latest version. After running these commands, you should be able to run cargo. ```sh curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh rustup update ``` -------------------------------- ### Install feroxbuster to current directory on Linux/macOS Source: https://github.com/epi052/feroxbuster/blob/main/README.md Installs feroxbuster to the current working directory on Linux (32 and 64-bit) and macOS. The script is fetched from the official repository and executed without arguments. ```bash curl -sL https://raw.githubusercontent.com/epi052/feroxbuster/main/install-nix.sh | bash ``` -------------------------------- ### Run all integration tests Source: https://github.com/epi052/feroxbuster/blob/main/tests/policies/README.md Commands to run the Python-only test, the Caddy test, and all integration tests. The Python test requires no external dependencies, while the Caddy test requires Caddy to be installed. ```bash # Run only Python-based test (no external deps needed) cargo test integration_auto_bail_cancels_scan_with_timeouts --test test_integration_caddy -- --exact --ignored # Run Caddy test (requires Caddy installation) cargo test integration_auto_bail_with_caddy --test test_integration_caddy -- --exact --ignored # Run all integration tests cargo test --test test_integration_caddy -- --ignored ``` -------------------------------- ### DynamicSemaphore usage example Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/sync.md Example from the type's own doc comment (src/sync/dynamic_semaphore.rs:19). Creates a DynamicSemaphore with capacity 2, acquires two permits, then reduces capacity to 1. When permits are dropped, only 1 permit will be available instead of 2. reduce_capacity returns the effective new capacity. ```rust use feroxbuster::sync::DynamicSemaphore; #[tokio::main] async fn main() { let semaphore = DynamicSemaphore::new(2); // Acquire permits let _permit1 = semaphore.acquire().await.unwrap(); let _permit2 = semaphore.acquire().await.unwrap(); // Reduce capacity from 2 to 1 (takes effect when permits are released) semaphore.reduce_capacity(1); // When permits are dropped, only 1 permit will be available instead of 2 // e.g. reduce_capacity returns the effective new capacity let effective = semaphore.reduce_capacity(1); } ``` -------------------------------- ### Install feroxbuster to a specific directory on Linux/macOS Source: https://github.com/epi052/feroxbuster/blob/main/README.md Installs feroxbuster to a specified directory on Linux (32 and 64-bit) and macOS. The script is fetched from the official repository and executed with the target directory as an argument. ```bash curl -sL https://raw.githubusercontent.com/epi052/feroxbuster/main/install-nix.sh | bash -s $HOME/.local/bin ``` -------------------------------- ### start_max_time_thread Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scan_manager.md Starts a background thread that enforces the maximum scan time limit. ```APIDOC ## start_max_time_thread ### Description Parses `config.time_limit` against `TIMESPEC_REGEX` (`N[smdh]`), sleeps that duration, then invokes `TermInputHandler::sigint_handler` (writes state file + exits). Started in `main::wrapped_main` unless `--parallel` is active (children enforce it individually). ### Signature ```rust pub async fn start_max_time_thread(handles: Arc) ``` ### Parameters - **handles** (`Arc`) - Required - Shared handles for the scan. ### Behavior - Parses the time limit from the configuration. - Sleeps for the specified duration. - Invokes the SIGINT handler to write state and exit. ``` -------------------------------- ### start_max_time_thread function signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scan_manager.md Parses config.time_limit against TIMESPEC_REGEX (N[smdh]), sleeps that duration, then invokes TermInputHandler::sigint_handler to write state file and exit. Started in main::wrapped_main unless --parallel is active. ```rust pub async fn start_max_time_thread(handles: Arc) ``` -------------------------------- ### Update feroxbuster Stats via direct methods and async send Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/statistics.md Shows how to create a Stats instance and update it directly via add_error and update_usize_field, with a commented example of the async path using handles.stats.send. ```rust use feroxbuster::{ statistics::{StatError, StatField, Stats}, Command::AddError, }; let stats = Arc::new(Stats::new(false)); stats.add_error(StatError::Timeout); // direct update stats.update_usize_field(StatField::TotalScans, 1); // async path (from Requester::request): // handles.stats.send(AddToUsizeField(StatField::TotalExpected, new_words.len())) ``` -------------------------------- ### Handle set_url parse failure and truncated body Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/response.md Error-handling example: a failed parse in set_url must not abort the scan; the source logs and keeps the old URL. Also shows checking the truncated flag and logging a warning with the content length. ```rust let mut resp = FeroxResponse::default(); resp.set_url("https://host/^\u{0}invalid"); // parse fails -> old url preserved, warning logged if resp.truncated() { log::warn!("body was cut at {} bytes", resp.content_length()); } ``` -------------------------------- ### initialize Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/client.md Builds a reqwest::Client with optional scope-aware redirect handling. ```APIDOC ## [Rust] initialize ### Description Create and return an instance of reqwest::Client with optional scope-aware redirect handling. ### Signature ```rust pub fn initialize(config: ClientConfig<'_, I>) -> Result where I: IntoIterator, I::Item: AsRef + std::fmt::Debug, ``` ### Parameters - **config** (ClientConfig<'_, I>) - Required - Configuration for the client ### Behavior - Redirect policy: `redirects && scope.is_empty()` → `Policy::limited(10)`; `redirects && scope` → custom policy following only in-scope URLs; otherwise `Policy::none()`. - Sets timeout, user_agent, `danger_accept_invalid_certs(insecure)`, default headers, redirect policy, and `.http1_title_case_headers()`. - Proxy (when non-empty): `Proxy::all(some_proxy)`. - Server certs: each path is read and parsed as PEM first, falling back to DER; invalid certs → context error. - mTLS: `reqwest::Identity::from_pkcs8_pem(&cert, &key)`; invalid identity → context error. ### Returns - A fully configured `reqwest::Client`, or a `Result` error on proxy parse failure, unreadable cert/key files, or invalid cert/identity data. ### Errors - `anyhow::Result`; cert/key/proxy errors bubble as `Err`. ### Example ```rust match client::initialize(client_config) { Ok(client) => { /* use client.request(...) */ } Err(e) => eprintln!("client build failed: {e}"), } ``` ``` -------------------------------- ### Standard bootstrap sequence from main::wrapped_main Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/event_handlers.md Initializes the stats, filters, and terminal output handlers, then creates the scan handler and sets up the handles. The comment notes that set_scan_handle must happen after Handles::new, and the output.send(AddHandles) is needed because TermOutHandler needs handles late. ```rust let (stats_task, stats_handle) = StatsHandler::initialize(config.clone()); let (filters_task, filters_handle) = FiltersHandler::initialize(); let (out_task, out_handle) = TermOutHandler::initialize(config.clone(), stats_handle.tx.clone()); let handles = Arc::new(Handles::new(stats_handle, filters_handle, out_handle, config.clone(), words)); let (scan_task, scan_handle) = ScanHandler::initialize(handles.clone()); handles.set_scan_handle(scan_handle); // must happen after Handles::new handles.output.send(AddHandles(handles.clone()))?; // TermOutHandler needs handles late filters::initialize(handles.clone()).await?; let tasks = Tasks::new(out_task, stats_task, filters_task, scan_task); ``` -------------------------------- ### Specify multiple extensions with -x Source: https://github.com/epi052/feroxbuster/blob/main/README.md Shows flexible ways to specify multiple values for options like -x. The command adds .pdf, .js, .html, .php, .txt, .json, and .docx to each URL. Multiple flags, space-separated, and comma-separated values are valid and interchangeable. ```bash ./feroxbuster -u http://127.1 -x pdf -x js,html -x php txt json,docx ``` -------------------------------- ### Configuration::new() signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/configuration.md Signature of the Configuration::new method. Builds the process-wide configuration with precedence: built-in defaults, then ferox-config.toml files, then command-line arguments. Returns Ok(Self) with clients rebuilt, or propagates errors wrapped with context by main.rs. ```rust pub fn new() -> Result ``` -------------------------------- ### DynamicSemaphore::new Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/sync.md Creates a new `DynamicSemaphore` with the specified initial capacity. ```APIDOC ## DynamicSemaphore::new ### Description Creates a new `DynamicSemaphore` with the specified initial capacity. ### Method `pub fn new(permits: usize) -> Self` ### Parameters - `permits` (usize) - Required - The initial maximum number of permits. ### Returns `Self` - A new `DynamicSemaphore` instance. ### Example ```rust use feroxbuster::sync::DynamicSemaphore; let semaphore = DynamicSemaphore::new(2); ``` ``` -------------------------------- ### Configuration Methods Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/configuration.md Documentation for the Configuration struct methods that are publicly callable. ```APIDOC ## Configuration::as_str ### Description Returns a debug string representation of the Configuration struct. ### Method N/A (Rust method) ### Endpoint N/A ### Parameters None ### Request Example N/A ### Response #### Success Response - **String** - Debug representation of the configuration #### Response Example ```rust let config = Arc::new(Configuration::new().unwrap()); let s = config.as_str(); ``` ``` ```APIDOC ## Configuration::as_json ### Description Creates an NDJSON representation of the current scan's Configuration. Serializes the struct with `serde_json::to_string` and appends a trailing newline. ### Method N/A (Rust method) ### Endpoint N/A ### Parameters None ### Request Example N/A ### Response #### Success Response - **Result** - NDJSON string representation of the configuration #### Response Example ```rust let config = Arc::new(Configuration::new().unwrap()); let json = config.as_json(); ``` ``` ```APIDOC ## Configuration::new ### Description Builds a Configuration exactly as the binary does, applying defaults, config files, and CLI overrides. ### Method N/A (Rust constructor) ### Endpoint N/A ### Parameters None ### Request Example N/A ### Response #### Success Response - **Result** - A fully configured Configuration instance #### Response Example ```rust let config = Arc::new(Configuration::new().unwrap()); assert_eq!(config.threads, 50); assert_eq!(config.depth, 4); assert_eq!(config.requester_policy, RequesterPolicy::Default); ``` ``` ```APIDOC ## Configuration::parse_config ### Description Deserializes a `ferox-config.toml` file explicitly. The binary scans the same path (e.g., CWD). ### Method N/A (Rust associated function) ### Endpoint N/A ### Parameters #### Path Parameters - **path** (PathBuf) - Required - Path to the TOML configuration file ### Request Example ```rust let cfg = Configuration::parse_config(PathBuf::from("./ferox-config.toml")).unwrap_or_default(); ``` ### Response #### Success Response - **Result** - Parsed Configuration from the TOML file #### Response Example ```rust let cfg = Configuration::parse_config(PathBuf::from("./ferox-config.toml")).unwrap_or_default(); ``` ``` -------------------------------- ### Calling make_request Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/utils.md Example call to make_request that returns the raw reqwest::Response. The function returns a Result, so the ? operator is used to propagate errors. ```rust // returns the raw reqwest::Response let response = make_request(client, url, method, data, level, &config, tx_stats).await?; ``` -------------------------------- ### Build Configuration and inspect defaults Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/configuration.md Builds a `Configuration` using `Configuration::new()` and asserts default values for `threads`, `depth`, and `requester_policy`. Requires `Arc` and the `RequesterPolicy` enum. ```rust use feroxbuster::config::{Configuration, RequesterPolicy}; let config = Arc::new(Configuration::new().unwrap()); assert_eq!(config.threads, 50); assert_eq!(config.depth, 4); assert_eq!(config.requester_policy, RequesterPolicy::Default); ``` -------------------------------- ### ClientConfig Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/client.md Configuration struct for initializing a reqwest client. ```APIDOC ## [Rust] ClientConfig ### Description Configuration struct for initializing a reqwest client. ### Fields - **timeout** (u64) - Required - Request timeout in seconds - **user_agent** (&'a str) - Required - User-Agent string sent on every request - **redirects** (bool) - Required - Whether redirects may be followed - **insecure** (bool) - Required - Accept invalid TLS certificates - **headers** (&'a HashMap) - Required - Default headers applied to every request - **proxy** (Option<&'a str>) - Required - Proxy URL (http(s):// or socks5(h)://); None disables - **server_certs** (Option) - Required - Iterable of certificate file paths (PEM or DER) - **client_cert** (Option<&'a str>) - Required - PEM-encoded X509 client certificate path (mTLS) - **client_key** (Option<&'a str>) - Required - PEM-encoded PKCS#8 private key path (mTLS) - **scope** (&'a [Url]) - Required - Allowed redirect/link-extraction domains ### Example ```rust use feroxbuster::{client, client::ClientConfig}; use std::collections::HashMap; use url::Url; let headers = HashMap::new(); let scope = vec![Url::parse("https://example.com").unwrap()]; let server_certs = vec!["/etc/ssl/private/rootCA.pem".to_string()]; let client_config = ClientConfig { timeout: 7, user_agent: "feroxbuster/2.13.1", redirects: true, insecure: true, headers: &headers, proxy: Some("http://127.0.0.1:8080"), server_certs: Some(server_certs), client_cert: Some("/path/client.crt"), client_key: Some("/path/client.key"), scope: &scope, }; ``` ``` -------------------------------- ### Resume a scan programmatically Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scan_manager.md Mirrors main.rs: loads a previous configuration, sets resumed and stdin flags, and rebuilds clients. Note that stdin is never re-read on resume and client is not serialized. ```rust use feroxbuster::scan_manager::resume_scan; let mut previous_config = resume_scan("ferox-https_example_com-1606947491.state"); previous_config.resumed = true; previous_config.stdin = false; // never re-read stdin on resume Configuration::try_rebuild_clients(&mut previous_config); // crate-internal; client is not serialized ``` -------------------------------- ### Create and switch to a new branch Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Creates a new branch on your local machine and switches to it. Replace [name_of_your_new_branch] with a branch name like 23-xxx. ```sh $ git checkout -b [name_of_your_new_branch] ``` -------------------------------- ### initialize function signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/client.md Function signature for `initialize`, which builds a `reqwest::Client` from a `ClientConfig`. It returns `anyhow::Result`; errors occur on proxy parse failure, unreadable cert/key files, or invalid cert/identity data. ```rust /// Create and return an instance of reqwest::Client with optional scope-aware redirect handling pub fn initialize(config: ClientConfig<'_, I>) -> Result where I: IntoIterator, I::Item: AsRef + std::fmt::Debug, ``` -------------------------------- ### Command enum definition Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/event_handlers.md Defines the message protocol for updating event handlers via an mpsc channel. Each variant is consumed by a specific handler (e.g., StatsHandler, ScanHandler) to trigger a corresponding effect, such as adding a request, starting a scan, or adjusting scan permits. ```rust /// Protocol definition for updating an event handler via mpsc #[derive(Debug)] pub enum Command { AddRequest, AddError(StatError), AddStatus(StatusCode), CreateBar(u64), AddToUsizeField(StatField, usize), SubtractFromUsizeField(StatField, usize), AddToF64Field(StatField, f64), Save, LoadStats(String), AddFilter(Box), RemoveFilters(Vec), Report(Box), ScanInitialUrls(Vec), ScanNewUrl(String), TryRecursion(Box), UpdateWordlist(Arc>), JoinTasks(Sender), Ping, Sync(Sender), AddDiscoveredExtension(String), WriteToDisk(Box), Exit, AddHandles(Arc), UpdateTargets(Vec), QueryOverallBarEta(Sender), AddScanPermits(usize), SubtractScanPermits(usize), } ``` -------------------------------- ### format method signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/url.md Simple helper to generate a `Url`. Errors during parsing `url` or joining `word` are propagated up the call stack. ```rust /// Simple helper to generate a `Url` /// /// Errors during parsing `url` or joining `word` are propagated up the call stack pub fn format(&self, word: &str, extension: Option<&str>) -> Result ``` -------------------------------- ### Pass auth token via query parameter with --query Source: https://github.com/epi052/feroxbuster/blob/main/README.md Passes an authentication token via a query parameter using --query. ```bash ./feroxbuster -u http://127.1 --query token=0123456789ABCDEF ``` -------------------------------- ### Include headers with -H Source: https://github.com/epi052/feroxbuster/blob/main/README.md Shows how to include custom headers using -H. Headers can be specified with multiple flags or comma-separated values. ```bash ./feroxbuster -u http://127.1 -H Accept:application/json "Authorization: Bearer {token}" ``` -------------------------------- ### Building candidate URLs for a word Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/url.md Core fuzzing transform in `Requester::request` that builds candidate URLs from a word and iterates over methods, applying deny-list and rate-limiting before requesting. ```rust let collected = self.handles.collected_extensions(); let urls = FeroxUrl::from_string(&self.target_url, self.handles.clone()) .formatted_urls(word, collected)?; for url in urls { for method in self.handles.config.methods.iter() { // deny-list -> rate-limit -> request } } ``` -------------------------------- ### Complete ferox-config.toml with full scan options Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/configuration.md A complete ferox-config.toml file that sets a wide range of scan options. Equivalent CLI flags are parenthetically noted in the source, but not shown inline. Defaults from the helper table apply for any omitted keys. ```toml wordlist = ["/usr/share/seclists/Discovery/Web-Content/raft-medium-directories.txt", "/custom/words.txt"] threads = 30 timeout = 10 rate_limit = 200 scan_limit = 2 depth = 2 status_codes = [200, 301, 302, 401, 403] filter_status = [404] extensions = ["php", "js", "html"] methods = ["GET", "POST"] headers = { "User-Agent" = "custom-agent", "Authorization" = "Bearer token" } queries = [["debug", "1"]] proxy = "http://127.0.0.1:8080" insecure = true collect_extensions = true collect_backups = true collect_words = true dont_filter = true output = "/tmp/results.txt" debug_log = "/tmp/ferox.log" json = true time_limit = "20m" scan_dir_listings = true unique = true save_state = false ``` -------------------------------- ### ClientConfig struct definition Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/client.md Defines the configuration struct for initializing a reqwest client. All fields are required; `server_certs` accepts an iterable of path-like items (e.g., `&Vec`). When `redirects` is true and `scope` is non-empty, a custom redirect policy is built that only follows in-scope URLs. ```rust /// Configuration struct for initializing a reqwest client pub struct ClientConfig<'a, I> where I: IntoIterator, I::Item: AsRef + std::fmt::Debug, { /// The timeout for requests in seconds pub timeout: u64, /// The User-Agent string to use for requests pub user_agent: &'a str, /// Whether to follow redirects pub redirects: bool, /// Whether to allow insecure connections pub insecure: bool, /// Headers to include in requests pub headers: &'a HashMap, /// Proxy server to use for requests pub proxy: Option<&'a str>, /// Server certificates to use for requests pub server_certs: Option, /// Client certificate to use for requests pub client_cert: Option<&'a str>, /// Client key to use for requests pub client_key: Option<&'a str>, /// scope for redirect handling pub scope: &'a [Url], } ``` -------------------------------- ### Requester::from constructor Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md Constructor for `Requester` from a `FeroxScanner` and its `FeroxScan`. When `config.rate_limit > 0`, a leaky-bucket `RateLimiter` is created via `build_a_bucket` (1-second interval, `refill = limit`, initial = half, max = limit; `limit` floored at 1) and `PolicyData::with_rate_limit` applies the cap. ```rust /// given a FeroxScanner, create a Requester pub fn from(scanner: &FeroxScanner, ferox_scan: Arc) -> Result ``` -------------------------------- ### Run Caddy server auto-bail test Source: https://github.com/epi052/feroxbuster/blob/main/tests/policies/README.md Run the Caddy server auto-bail integration test with exact match, ignored flag, and nocapture to see output. ```bash cargo test integration_auto_bail_with_caddy --test test_integration_caddy -- --exact --ignored --nocapture ``` -------------------------------- ### Verify SHA512 checksum for x86_64 Windows binary Source: https://github.com/epi052/feroxbuster/blob/main/choco_package/legal/VERIFICATION.txt Run this command to verify the SHA512 checksum of the x86_64 Windows feroxbuster executable zip file. ```shell checksum -t sha512 -f .\x86_64-windows-feroxbuster.exe.zip ``` -------------------------------- ### Verify SHA512 checksum for x86 Windows binary Source: https://github.com/epi052/feroxbuster/blob/main/choco_package/legal/VERIFICATION.txt Run this command to verify the SHA512 checksum of the x86 Windows feroxbuster executable zip file. ```shell checksum -t sha512 -f .\x86-windows-feroxbuster.exe.zip ``` -------------------------------- ### Run the test suite Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Runs the test suite for the feroxbuster project. Ensure all tests pass before sharing your code. ```sh $ cd ~/projects/feroxbuster $ cargo test ``` -------------------------------- ### Switch to main branch Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Switches to the main branch if you are not already on it. Resolve outstanding files and commits before running. ```sh $ git checkout main ``` -------------------------------- ### Run Python server auto-bail test Source: https://github.com/epi052/feroxbuster/blob/main/tests/policies/README.md Run the Python server auto-bail integration test with exact match, ignored flag, and nocapture to see output. ```bash cargo test integration_auto_bail_cancels_scan_with_timeouts --test test_integration_caddy -- --exact --ignored --nocapture ``` -------------------------------- ### Switch to main branch Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Switch to the main branch if the working directory is not clean or you are not on main. ```sh git checkout main ``` -------------------------------- ### CLI command with rate limit and auto-tune Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md CLI equivalent that exercises the same rate-limiting and auto-tune machinery as the Requester test pattern, including --collect-words. ```bash feroxbuster -u https://example.com -w words.txt --rate-limit 100 --auto-tune --collect-words ``` -------------------------------- ### resume_scan function signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scan_manager.md Loads a Configuration from a JSON state file, deserializes config, preloads RESPONSES, and returns the stored Configuration. Exits with process::exit(1) on failure after logging specific error messages. ```rust /// Primary logic used to load a Configuration from disk and populate the appropriate data /// structures pub fn resume_scan(filename: &str) -> Configuration ``` -------------------------------- ### resume_scan Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scan_manager.md Resume a scan by loading a Configuration from a JSON state file. ```APIDOC ## resume_scan ### Description Reads the JSON state file, deserializes `config`, preloads `RESPONSES` from `responses`, and returns the stored `Configuration`. Failure exits with `process::exit(1)` after logging. ### Signature ```rust pub fn resume_scan(filename: &str) -> Configuration ``` ### Parameters - **filename** (`&str`) - Required - Path to the JSON state file. ### Returns - **Configuration** - The deserialized configuration from the state file. ### Errors Exits with `process::exit(1)` after logging one of the following messages: - `"Could not open state file, exiting"` - `"Could not load configuration from state file, exiting"` - `"Could not deserialize configuration found in state file, exiting"` ``` -------------------------------- ### PolicyData::new constructor Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md Creates a new PolicyData from a RequesterPolicy and timeout. The wait_time is set to min((timeout / 2) * 1000 ms, 30_000 ms) and used as the cooldown between tuning adjustments. ```rust /// given a RequesterPolicy, create a new PolicyData pub fn new(policy: RequesterPolicy, timeout: u64) -> Self ``` -------------------------------- ### Handle errors with context, explicit match, and skip_fail! Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/errors.md Patterns for handling non-exiting failures in consumer code. Use `with_context` to propagate errors with context, `match` to handle errors explicitly, and `skip_fail!` to tolerate expected failures. Interactive menu and policy errors are logged instead of propagated. ```rust // propagate with context let config = Arc::new(Configuration::new().with_context(|| "Could not create Configuration")?); ``` ```rust // handle explicitly match HeuristicTests::new(handles.clone()).connectivity(&targets).await { Ok(live) => /* scan */, Err(e) => { clean_up(handles, tasks).await?; bail!(fmt_err(&e.to_string())); // "ERROR: ..." printed by main } } ``` ```rust // tolerate expected failures (skip_fail!) let request = skip_fail!(url.format("", None)); ``` -------------------------------- ### Stage all unstaged files Source: https://github.com/epi052/feroxbuster/blob/main/CONTRIBUTING.md Stage all unstaged files. Use with caution as it may add files you don't want to commit. ```sh git add . ``` -------------------------------- ### Calling filters::initialize in main.rs Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/filters.md Call to `filters::initialize` from `src/main.rs`, passing a clone of the `handles` Arc. This is the invocation point for the filter initialization routine. ```rust // src/main.rs filters::initialize(handles.clone()).await?; ``` -------------------------------- ### DynamicSemaphore::acquire Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/sync.md Acquires one permit from the semaphore, waiting if none are currently available. ```APIDOC ## DynamicSemaphore::acquire ### Description Acquires one permit from the semaphore, waiting if none are currently available. ### Method `pub async fn acquire(&self) -> Result, tokio::sync::AcquireError>` ### Returns - `Result, tokio::sync::AcquireError>` - A permit on success, or an `AcquireError` if the semaphore is closed. ### Example ```rust let permit = semaphore.acquire().await.unwrap(); ``` ``` -------------------------------- ### logger::initialize function signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/message.md Creates a customized env_logger::Logger with timer offset/color and sets log level based on verbosity. Respects RUST_LOG if set. ```rust /// Create a customized instance of env_logger::Logger with timer offset/color and set the log /// level based on `verbosity` pub fn initialize(config: Arc) -> Result<()> ``` -------------------------------- ### DynamicSemaphore::try_acquire Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/sync.md Attempts to acquire one permit without blocking. Returns immediately if no permits are available. ```APIDOC ## DynamicSemaphore::try_acquire ### Description Attempts to acquire one permit without blocking. Returns immediately if no permits are available. ### Method `pub fn try_acquire(&self) -> Result, tokio::sync::TryAcquireError>` ### Returns - `Result, tokio::sync::TryAcquireError>` - A permit on success, or a `TryAcquireError` if no permits are available or the semaphore is closed. ### Example ```rust match semaphore.try_acquire() { Ok(permit) => { /* use permit */ } Err(_) => { /* handle failure */ } } ``` ``` -------------------------------- ### Requester test pattern with event handlers Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/scanner.md Standalone test pattern for the Requester, initializing configuration, event handlers, and a FeroxScan before constructing a Requester from a FeroxScanner. Requires the feroxbuster crate and its modules; the comment indicates to scan, wait, and drop. ```rust use feroxbuster::{ config::Configuration, event_handlers::{Handles, Tasks, FiltersHandler, StatsHandler, TermOutHandler}, scanner::{FeroxScanner, Requester}, scan_manager::{FeroxScan, ScanOrder, ScanType}, }; use std::sync::Arc; let config = Arc::new(Configuration::new().unwrap()); let (stats_task, stats_handle) = StatsHandler::initialize(config.clone()); let (filters_task, filters_handle) = FiltersHandler::initialize(); let (out_task, out_handle) = TermOutHandler::initialize(config.clone(), stats_handle.tx.clone()); let wordlist = Arc::new(vec!["admin".to_string(), "api".to_string()]); let handles = Arc::new(Handles::new(stats_handle, filters_handle, out_handle, config.clone(), wordlist)); let (scan_task, scan_handle) = ScanHandler::initialize(handles.clone()); handles.set_scan_handle(scan_handle); filters::initialize(handles.clone()).await.unwrap(); let scan = FeroxScan::new("https://example.com", ScanType::Directory, ScanOrder::Initial, 1000, OutputLevel::Default, None, true, handles.clone()); let requester = Requester::from(&FeroxScanner::new("https://example.com", ScanOrder::Initial, wordlist, Arc::new(DynamicSemaphore::new(0)), handles.clone()), scan).unwrap(); // scan, wait, drop ``` -------------------------------- ### Scan IPv6 address with no recursion and verbose logging Source: https://github.com/epi052/feroxbuster/blob/main/README.md Scans an IPv6 address without recursion and enables INFO-level logging with -vv. ```bash ./feroxbuster -u http://[::1] --no-recursion -vv ``` -------------------------------- ### DynamicSemaphore::available_permits Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/sync.md Returns the number of currently available (free) permits. ```APIDOC ## DynamicSemaphore::available_permits ### Description Returns the number of currently available (free) permits. ### Method `pub fn available_permits(&self) -> usize` ### Returns `usize` - The number of free permits. ### Example ```rust let available = semaphore.available_permits(); ``` ``` -------------------------------- ### make_request with stats reporting Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/utils.md Shows how to manually drive a request with stats reporting, as used in the `Extractor::make_extract_request` path (`src/extractor/container.rs:627`). The call passes the client, URL, default method, no body, output level, config, and a clone of the stats transmitter, then awaits the result. ```rust let response = make_request( client, &url, DEFAULT_METHOD, None, self.handles.config.output_level, &self.handles.config, self.handles.stats.tx.clone(), ) .await?; ``` -------------------------------- ### Send an async ack-gated command (oneshot channel) Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/event_handlers.md Shows the pattern for sending a command and waiting for the handler to process it. Uses a oneshot channel to synchronize, sending a TryRecursion command followed by a Sync command, then awaiting the receiver. ```rust let (tx, rx) = oneshot::channel::(); handles.send_scan_command(Command::TryRecursion(Box::new(response)))?; handles.send_scan_command(Command::Sync(tx))?; // wait until the handler processed TryRecursion rx.await?; ``` -------------------------------- ### FeroxResponse Display Implementation Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/response.md Renders a FeroxResponse as a formatted string: `FeroxResponse { url: ..., method: ..., status: ..., content-length: ... }`. ```APIDOC ## FeroxResponse Display Implementation ### Description Renders a `FeroxResponse` as a formatted string: `FeroxResponse { url: ..., method: ..., status: ..., content-length: ... }`. ### Method `fmt::Display` ### Example Output ``` FeroxResponse { url: http://example.com, method: GET, status: 200, content-length: 1234 } ``` ``` -------------------------------- ### try_rebuild_clients() signature Source: https://github.com/epi052/feroxbuster/blob/main/_autodocs/api-reference/configuration.md Signature of the try_rebuild_clients method. Rebuilds configuration.client when proxy, timeout, UA, redirects, insecure, headers, resumed, server certs, client cert, or client key differ from defaults; builds replay_client when replay_proxy is non-empty. ```rust fn try_rebuild_clients(configuration: &mut Configuration) ```