Available on Crates.io: https://crates.io/crates/dalfox-rs
A strictly-typed, asynchronous Rust binding for the Dalfox XSS Scanner (v3+).
dalfox-rs wraps the Dalfox binary, parses its JSON output into typed Rust structs, and makes XSS scanning composable inside fuzzers, proxies, or CI/CD pipelines.
- Dalfox v3 CLI — scan, file, and pipe modes with typed builder flags
- Dalfox v3 finding shape — parses v3 JSON without legacy
poc; usefinding.poc_url()orfinding.data - Streaming callbacks —
*_streamingmethods use--format jsonland emit findings as lines when present - Stored XSS —
--sxss/--sxss-urlondalfox scan - Multi-format output — JSON, CSV, Markdown, and plain text via
format_as() - Diagnostic capture — stderr, parse errors, exit codes, structured Dalfox error JSON
- Result filtering — query by severity, event type, or verified status
These upstream Dalfox v3 flags are not exposed by the builder or argv helpers today:
--input-type raw-http/--input-type har(file mode scans URL lists only; seescan_file_raw()docs)- Blind OOB variants beyond
--blind(--blind-oob*, custom blind payloads) --format sarif/--format toml--config,--dry-run,--encoders,--force-waf,--include-request,--max-concurrent-targets--retry-delay,--stream-findings,--waf-bypass--sxss-method,--sxss-retries
Gap tests in tests/gap.rs pin each cluster until wired or explicitly rejected.
[dependencies]
dalfox-rs = "0.5.5"
tokio = { version = "1", features = ["full"] }Prerequisite: Dalfox v3 (major ≥ 3) must be in your system $PATH or specified via .binary_path().
MSRV: rust-version in Cargo.toml is the minimum to build the library (cargo check). Running the full test suite may require a newer stable toolchain because of dev-dependencies (see CI).
From crates.io (recommended): install the upstream scanner separately:
cargo install dalfox --lockedFrom a git checkout of this repo: the repo includes setup.sh (not shipped in the crates.io tarball):
git clone https://github.com/santhreal/dalfox-rs.git
cd dalfox-rs
./setup.sh # auto: cargo, Homebrew, or release binary
# or: ./setup.sh --binary # download to ~/.local/binHomebrew: brew install dalfox
scan_pipe() writes URLs to Dalfox stdin. If you wrap the binary with Docker, the shim must keep stdin open (docker run -i or equivalent). A non-interactive docker run without -i drops stdin and Dalfox may return NO_TARGETS.
use dalfox_rs::{Dalfox, DalfoxResult, OutputFormat};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let runner = Dalfox::builder()
.request_timeout(10) // per-request timeout (seconds)
.scan_deadline(300) // overall scan deadline (seconds)
.workers(50)
.build();
let result: DalfoxResult = runner.scan_url("http://example.com?q=test").await?;
for finding in &result.findings {
println!("{}", finding); // Display impl gives readable output
}
// Output as CSV for spreadsheet import
println!("{}", result.format_as(OutputFormat::Csv));
Ok(())
}*_streaming methods pass --format jsonl to Dalfox. Each verified finding line is parsed and forwarded to your callback as it arrives (meta-only lines are ignored):
let result = runner.scan_url_streaming("http://example.com?q=test", |finding| {
eprintln!("LIVE: {}", finding);
}).await?;Detect persistent XSS via separate injection and trigger URLs:
let result = runner.scan_sxss(
"http://example.com/comment?body=test", // inject here
"http://example.com/view-comments", // check here
).await?;let runner = Dalfox::builder()
.waf_evasion(true)
.cookie("session_id=12345")
.header("Authorization: Bearer my_token")
.delay(500)
.rate_limit(20)
.scan_timeout(120)
.retries(2)
.insecure(true)
.param("id,q,lang") // repeated --param id --param q --param lang
.payload("payloads.txt") // file path for --custom-payload
.blind_callback("https://my.callback.domain.com")
.follow_redirects(true)
.ignore_return("302,403,404")
.binary_path("/usr/local/bin/dalfox")
.build();let verified = result.verified_findings();
let critical = result.high_severity_findings();
if result.has_parse_errors() {
eprintln!("Warning: {} output lines failed to parse", result.parse_errors.len());
}| Mode | Method | Description |
|---|---|---|
| URL | scan_url() |
Scan a single target URL |
| File | scan_file_raw() |
Scan targets from a newline-separated URL list file |
| Pipe | scan_pipe() |
Pipeline multiple URLs via stdin |
| Stored XSS | scan_sxss() |
Detect persistent XSS |
All modes have _streaming variants for jsonl finding callbacks.
MIT License