CLI tool
hahwul/dalfox avatar
hahwul/dalfox

dalfox: an XSS scanner rebuilt in Rust, with an unusually honest changelog

🌙🦊 Dalfox is a powerful open-source XSS scanner and utility focused on automation.

5,298 stars568 forksRustMIT

At a glance

What is it?
Dalfox scans URLs, files, piped input and raw HTTP for reflected, stored and DOM XSS, and ships as a single binary. The version 3 rewrite and its release notes say more about how the tool behaves than the README does.
Who is it for?
Dalfox is a good fit for a security engineer who already knows what reflected, stored and DOM XSS look like and wants one binary that covers all three plus parameter discovery. It is a poor fit as a first lesson in XSS, since the flag surface assumes you already know what you are looking for, and a poor fit for a large continuous crawl, since it is an active scanner rather than a queue-backed service.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 15 days ago.
What is it written in?
Mainly Rust, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

A Rust rewrite that kept the old language on a side branch

Dalfox describes itself as an open-source XSS scanner and utility focused on automation, and the repository metadata says what that means in practice: the language is Rust, the licence is MIT, and the topics are bugbounty, devsecops, security and xss. The last push was on 2026-09-22 and the default branch is `main`, so this is a project with recent commits rather than an archived one.

The one structural fact worth knowing before anything else is that version 3 is a rewrite. The README says plainly that v3 is a complete rewrite in Rust, that the Go codebase is preserved on the `v2` branch and continues to receive security backports, and that the support policy lives in SECURITY.md with a separate migration guide covering what changed. That arrangement matters for anyone with an existing pipeline, because the flags and output are not guaranteed to carry over, and because the older tool is still being patched for security issues on its own terms.

So there are two dalfox tools with the same name. The one on `main` is Rust, and the one on `v2` is Go and still maintained for security only.

Five ways to install, and one that builds from source

Installation is the most polished part of the README, and it covers the platforms people actually run scanners on.

bash
brew install dalfox

That covers macOS and Linux through Homebrew. On Ubuntu the Snap route is one command:

bash
sudo snap install dalfox

Arch users have the AUR through either of the two common helpers:

bash
yay -S dalfox
paru -S dalfox

Nix and NixOS are covered twice, once as a plain package and once through flakes. The README flags a caveat for the package version: the latest releases might only be present in the `unstable` channel. The flake form runs the scanner straight from GitHub without installing anything:

bash
nix run github:hahwul/dalfox -- scan https://example.com

The flake also exposes `overlays.default`, so a NixOS or home-manager user can build dalfox against their own nixpkgs rather than the pinned set. If none of that fits, prebuilt binaries are on the GitHub releases page, including statically linked musl variants for Linux, and the installation guide covers building from source by hand.

Four subcommands, and a discovery phase that runs before scanning

The usage line is short, and the mode list is where the design shows:

bash
dalfox [mode] [target] [flags]

The README lists four subcommands: `scan`, `server`, `payload` and `mcp`. That is a wider surface than the single mode most scanners expose, and it changes what kind of tool this is. `server` and `mcp` mean it can sit inside another workflow, with the MCP stdio server in particular aimed at driving scans from an agent or editor rather than from a terminal.

Targets are auto-detected, and the README shows one example per shape:

bash
dalfox scan http://example.com -b https://callback
cat urls.txt | dalfox scan --headers "AuthToken: xxx"

The feature list separates a discovery phase from a scanning phase. Discovery covers parameter analysis, static analysis, BAV testing and parameter mining. Scanning covers reflected, stored (SXSS) and DOM-based XSS, with what the README calls DOM and AST verification. Separating the two phases is the interesting choice, because a finding is only as good as the injection point it was found through, and automatic discovery tends to produce synthetic points.

Around that sit WAF fingerprinting with confidence scoring and a `--waf-min-confidence` threshold, custom payloads, remote wordlists, and output in JSON, JSONL, plain, Markdown, SARIF or TOML, including silence mode and detailed reports.

What the release notes admit about getting it wrong

The three most recent releases are worth reading closely, because the changelog spends its space on the scanner having been wrong rather than on new commands.

Version 3.2.1, published on 2026-08-13, is a false-positive and recall fix. The note describes parameter mining collapsing away a real finding: a page echoing its whole query string used to report a proof of concept against a synthetic `any` parameter while missing the real one, so mining now folds away only what it mined itself. The same release fixed a 5xx page reflecting the payload ending the DOM phase, a panic on non-ASCII Trusted Types callbacks being swallowed into a `0 XSS` result with exit code 0, and quadratic HTML-nesting parses. A scan that reports clean without scanning is the worst failure mode a security tool has, and it is listed here as fixed rather than hypothetical.

Version 3.2.2, on 2026-08-31, hardened request construction and input validation: a raw-HTTP `//` target that could hijack the Host header, a duplicate `Content-Type`, HAR input with empty cookies, and query injection leaking into the URL fragment. It also fixed an MCP hang on Windows caused by caching the scan runtime in thread-local storage, and stopped config files from overriding flags you typed explicitly.

Version 3.2.3, on 2026-09-15, is the security release. A scanned page could choose where dalfox sent the operator's own `-H` headers and `--cookies`, so cross-origin `<form action>` targets are no longer probed during parameter discovery, and `--follow-redirects` now stops when a chain leaves the origin it started on. Reading these three together tells you where the tool is most likely to hurt you: credential handling, redirect following, and input parsing at the request layer.

Dependency comments in Cargo.toml that read like incident reports

Some projects leave their dependency files clean. Dalfox leaves its reasons in, and the comments explain real constraints.

toml
name = "dalfox"
version = "3.2.3"
edition = "2024"
rust-version = "1.93"
license = "MIT"

The crate requires Rust 1.93 or newer and sits on edition 2024. reqwest is pulled in with TLS support handled manually: the `rustls-no-provider` feature leaves the crypto provider unset so the process can install ring's as the default. The comment on the `rustls` line explains why, and the reason is portability rather than preference. The default `aws-lc-rs` backend ships C and assembly that fails to link on several distributions including the AUR and musl targets, while ring's prebuilt assembly is portable.

The scraper entry is commented at length too. The `errors` feature makes every parsed `Html` retain a vector of heap-allocated messages per tokenizer parse error for the lifetime of the document. The comment works out that a body of malformed characters produces one allocation per byte, so a 16 MiB body generated roughly 16.7 million allocations and one to two gigabytes of resident memory from a 521 KB gzipped response. Nothing in dalfox ever reads those errors, only walks the tree, so the feature is dropped. That is a memory ceiling reasoned out in a comment next to the line that fixes it, which is more informative than most changelogs.

A Dockerfile that builds as non-root, and a justfile that knows the build

The container build is a standard cargo-chef layout: a Rust Alpine image installs build-base, musl-dev, openssl and perl, then cargo-chef prepares a recipe, cooks it separately from the source copy, and builds the release binary before the final stage drops to `alpine:3.24` with only openssl and libgcc installed. It creates an `app` group and user, copies the release binary into `/app`, chowns it, switches with `USER app`, and runs `./dalfox` as the command.

One detail is worth a second look: the builder image is `rust:1.98.0-alpine3.23` while `Cargo.toml` declares `rust-version = "1.93"`. The declared minimum and the toolchain used to produce official images are not the same number, which is normal, but it does mean the floor in the manifest is the only thing constraining a local build.

The `justfile` covers the rest of the loop with named recipes, including a `man` task that renders the roff man page from the freshly built binary into `target/`, a `nix-check` that evaluates every flake output across all supported systems without building, and a `fix` recipe that runs `cargo fmt` followed by `cargo clippy --fix --allow-dirty`. The `examples/` directory holds `config.toml`, `sample_request.txt` and `sample_targets.txt`, so the configuration file format and the raw HTTP input format are both readable without running anything. Documentation is served from `docs/` with `hwaro serve`, and the CLI reference plus quick start on dalfox.hahwul.com are where the flag list actually lives.

Editorial conclusion

Dalfox is a good fit for a security engineer who already knows what reflected, stored and DOM XSS look like and wants one binary that covers all three plus parameter discovery. It is a poor fit as a first lesson in XSS, since the flag surface assumes you already know what you are looking for, and a poor fit for a large continuous crawl, since it is an active scanner rather than a queue-backed service. Before adopting it, read the v3 migration guide and the support policy on the v2 branch, then check the CLI reference for the output format your pipeline consumes, because SARIF and JSONL are the two that most CI setups want and the README mentions them only in passing.

Frequently asked questions

Is Dalfox still written in Go?

Not on the main branch. Version 3 is a complete rewrite in Rust, and the facts around it say Rust as the language. The Go implementation is preserved on the `v2` branch and still receives security backports, with the support policy in SECURITY.md and a separate migration guide describing what changed in v3.

Can Dalfox scan a whole list of URLs at once?

Yes. The README lists file mode and pipeline mode alongside single URLs and raw HTTP, and all four are auto-detected, so you pass a target and the tool works out the shape. Custom payloads and remote wordlists can be supplied the same way, and `--headers` lets an authenticated session be reused across a piped list.

Does Dalfox find stored and DOM XSS, or only reflected?

All three. The feature list names reflected, stored (SXSS) and DOM-based XSS, with DOM and AST verification, and a separate discovery phase covering parameter analysis, static analysis, BAV testing and parameter mining runs before scanning. Version 3.2.1 also fixed a case where a 5xx page reflecting the payload would end the DOM phase early.

What formats can Dalfox export findings in?

JSON, JSONL, plain, Markdown, SARIF and TOML, plus a silence mode and detailed reports. For a CI pipeline the two that usually matter are SARIF for code scanning dashboards and JSONL for streaming results into another tool. The README lists the formats without examples, so the CLI reference is where to check the exact shape of each.

Official sources

  1. hahwul/dalfox on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/hahwul-dalfox.svg)](https://hysenlabs.com/projects/hahwul-dalfox)