av dast scan
Scan a running web application or API and tier every finding RED YELLOW GREEN.
Synopsis
Section titled “Synopsis”av dast scan --target <url> [flags]The binary ships as alertavuln; av is the common alias - they are
interchangeable in every example.
Description
Section titled “Description”av dast scan runs the bundled scanners against a running target URL, and
normalises everything they emit into a single finding set rendered as a table
(or JSON with --json). A local scan runs on your own machine, costs nothing,
and is not metered.
Scans are passive by default: the scanners crawl the target and observe its
responses without sending attack traffic, so a passive scan is non-intrusive
and safe to run anywhere, including production. Add --active to also run
attack-payload rules; --intensity tunes how aggressive an active run is
(request rate, concurrency, and time budget). --active is gated for
production - see the authorization note above.
Before any scanner runs, a target other than localhost must pass an
ownership check. You must be logged in (av login); the CLI sends the
target URL and scan mode to AlertaVuln, which confirms that your organisation’s
plan includes DAST (the Attack Scanning module for --active) and that your
organisation has verified the target’s domain - see
Prove you control the domain. A
verified domain covers every host under it. A raw IP address is refused, since
there is no domain to verify. If the check fails, the scan is refused with the
reason and nothing runs. localhost and other loopback addresses are your own
machine: they skip the check, need no login, and work offline.
Pass --project to upload the findings to that project so they appear on its
Dynamic Scan page. The target’s git ref is detected from the working tree’s
git metadata and recorded as provenance. --no-upload keeps a scan local-only
even when --project is set. The --target value must be an absolute
http(s) URL; any credentials embedded in it are stripped before the URL
reaches the engines, the upload, or any log.
For CI gating, --fail-on makes the command exit non-zero when the worst
finding is at or above the given tier.
Options
Section titled “Options”| Flag | Default | Description |
|---|---|---|
--target |
- | Target base URL to scan (required; absolute http(s) URL) |
--project |
- | Project ID to upload findings to (omit for a local-only scan) |
--json |
false |
Output the scan as JSON instead of a table |
--export |
- | Export to a directory or file (HTML; raw JSON with --json) |
--no-upload |
false |
Scan locally only; do not upload even if --project is set |
--fail-on |
none |
Exit non-zero if the worst finding is at or above the tier: red, yellow, or none |
--active |
false |
Run active (attack-payload) rules in addition to the passive checks |
--intensity |
low |
Scan intensity (rate, concurrency, time budget): low, medium, or high |
--environment |
staging |
Target environment: staging, production, or internal (gates --active) |
--i-am-authorized |
false |
Attest you own or are authorized to test the target (required non-interactively; also gates --active against production) |
--seed-urls |
- | File of newline-separated same-site URLs to seed the crawl (SPAs, APIs); also fed to the template-scanner, which checks each URL |
--openapi |
- | OpenAPI/Swagger spec (http(s) URL or local file) to seed the web-scanner’s crawl. The template-scanner does not use the spec; the scan prints a notice saying so |
--ajax-spider |
false |
Also crawl with a headless browser to find pages a client-rendered app builds in JavaScript. Slower. Needs a container runtime, or Firefox on PATH for a native run (otherwise the scan prints a notice and runs the standard crawl). Env: ALERTAVULN_DAST_AJAX_SPIDER=1 |
Examples
Section titled “Examples”Passive scan of a running staging site (you confirm authorization at the prompt):
av dast scan --target https://staging.example.comScan and upload the findings to a project’s Dynamic Scan page:
av dast scan --target https://staging.example.com --project <projectId>Gate a CI pipeline - non-interactive, so authorization is attested with the flag, and the run exits non-zero on a RED finding:
av dast scan --target https://staging.example.com \ --i-am-authorized --fail-on red --jsonRun an active scan (attack payloads) against a non-production target at higher intensity:
av dast scan --target https://staging.example.com \ --active --intensity high --i-am-authorizedActive scan of a production target - permitted only with the explicit attestation:
av dast scan --target https://app.example.com \ --environment production --active --i-am-authorizedScan a single-page app: seed the routes a crawler cannot find, and add the browser crawl for pages the app builds in JavaScript:
av dast scan --target https://staging.example.com \ --seed-urls ./urls.txt --ajax-spiderHow the scanners run
Section titled “How the scanners run”The web-scanner runs in a container when Docker or Podman is on PATH,
using a pinned image. Without a container runtime it runs natively, which needs
Java. Both ways run the same scan plan: the same crawl, seeds, authentication
and report. If neither is available, the web-scanner is skipped with a notice
and the template-scanner still runs (a form login
needs the web-scanner, so that scan fails with a clear message instead).
- Local targets work from the container. For a
localhostor127.0.0.1target, the CLI points the container at your machine and maps every finding back to the URL you typed. - Linux and
127.0.0.1-only services. On Linux the container reaches your machine through its host-gateway address, which cannot see a service bound only to127.0.0.1, so a Linux scan of a loopback target prints a notice about it. If the service listens only on127.0.0.1, bind it to0.0.0.0, or run the scan where no container runtime is onPATH, so theweb-scannerruns natively. - Your identity on Linux. The container runs as your own user, so it can read and write the scan’s private working folder. Rootless Podman and rootless Docker are handled as well.
Seed URLs and OpenAPI specs
Section titled “Seed URLs and OpenAPI specs”--seed-urls reaches both scanners: the web-scanner imports the URLs before
it crawls, and the template-scanner runs its checks against each one.
--openapi seeds the web-scanner’s crawl only; the template-scanner does
not use the spec, and the scan prints ! OpenAPI seed applies to the web-scanner only. Seeds outside the target’s site are dropped. See
Help us find your pages for how to
build a seed list or find your spec.
Browser crawl (--ajax-spider)
Section titled “Browser crawl (--ajax-spider)”The standard crawl follows links in the HTML. A client-rendered app builds many
of its pages in JavaScript, so --ajax-spider (or
ALERTAVULN_DAST_AJAX_SPIDER=1) adds a second crawl that drives a headless
browser. With a form login, the browser crawl runs as the signed-in user too.
It is opt-in because it is slower: it gets the same time limit as the standard
crawl, taken from the web-scanner’s share of the time budget.
The container image includes the browser. A native run needs Firefox on
PATH. When the browser crawl cannot run, the scan prints one of these notices
and continues with the standard crawl:
! browser crawl skipped: no Firefox on PATH for the web-scanner to drive; the standard crawl still runs! browser crawl skipped: the web-scanner could not start a browserScan templates
Section titled “Scan templates”The template-scanner checks the target against a pinned set of scan templates.
The first scan downloads that set once (about 10 MB), verifies its checksum, and
keeps it in the CLI’s engine cache next to the scanners. Later scans reuse it,
and a scan never fetches templates of its own, so the same CLI version always
scans with the same templates.
On a machine that cannot reach the download, point the CLI at an extracted copy
instead. Copy the alertavuln/bin/templates/<version> folder from the user
config directory of a machine where a scan has run, then:
export ALERTAVULN_DAST_TEMPLATES_DIR=/path/to/templatesWhen the variable is set, nothing is downloaded. It must name an extracted copy
of the templates (a directory with the http folder at its top); anything else
is refused with a notice. A relative path is resolved against the directory you
run the scan from. If no templates are available, the template-scanner does not run,
the scan says why on stderr, and the web-scanner results still stand.
What a passive scan checks
Section titled “What a passive scan checks”A passive scan sends no attack payloads. The two scanners cover it like this:
- The
web-scannercrawls the target (and any seed URLs), then checks every response it saw: security headers, cookies, information leaks, and similar. - The
template-scannerruns a bounded set of checks against the target and each seed URL: missing or deprecated security headers, tokens or keys exposed in a response, revealing headers, site files such asrobots.txtandsecurity.txt, and, for anhttpstarget, certificate and TLS protocol checks (expired or self-signed certificates, weak ciphers, deprecated TLS versions). That is under 100 requests per URL, so a low-intensity scan with a handful of seed URLs finishes well inside its time budget.
A passive scan does not run CVE checks, exploit-shaped checks (path traversal,
injection or cache-poisoning probes that carry attack payloads), or any
intrusive, fuzzing or denial-of-service check. --active adds the intrusive
and fuzzing checks.
Both tiers stay on the URL you typed. TLS checks run only against an https
target, and no check probes other ports or services on the host.
Out-of-band detection is off. A scan never registers with an outside interaction server, and never makes the target call one. Checks that can only confirm a finding through such a callback (some blind injection and server-side request checks) do not run.
Time budget
Section titled “Time budget”--intensity sets the time budget for the whole scan:
| Intensity | Whole scan | web-scanner share (default passive scan) |
Left for the template-scanner (at least) |
|---|---|---|---|
low |
15 min | 8 min | 7 min |
medium |
30 min | 13 min | 17 min |
high |
60 min | 23 min | 37 min |
The web-scanner runs first, inside its own share: its crawl limit, a
two-minute wait for its analysis, and a minute to start and write its report.
--ajax-spider adds a second crawl of the same length, and --active adds an
attack phase of the same length. The template-scanner then runs until the
whole-scan budget ends, so it also gets any time the web-scanner did not use.
In a default passive scan, neither scanner can use up the other’s time.
The opt-in phases make the web-scanner’s share larger, but never larger than
the whole scan less 2 minutes. The template-scanner always keeps at least
those 2 minutes, which cover its passive checks on the target and a handful of
seed URLs at low intensity.
| Intensity | web-scanner share with --active or --ajax-spider |
With both |
|---|---|---|
low |
13 min (2 min left for the template-scanner) |
13 min (2 min left) |
medium |
23 min (7 min left) | 28 min (2 min left) |
high |
43 min (17 min left) | 58 min (2 min left) |
With both options, the web-scanner’s phases can add up to more than its
share. On a small site they finish early, and the template-scanner also gets
the time the web-scanner leaves unused. On a large site the web-scanner can
reach the end of its share before it writes its report; it is then failed,
with the reason stopped at its time budget, and only the template-scanner’s
findings are kept. On a large site, run the two options in separate scans, and
raise --intensity when you add either one.
The template-scanner reports each finding as it finds it. If the budget runs
out before it finishes, the findings it reported before then are kept and
uploaded like any others, and the scan says so (see
Engine status). A template-scanner cut off with results
already reported is partial; one cut off before it reported anything is
failed, with the reason stopped at its time budget.
Engine status
Section titled “Engine status”When one scanner does not complete but the other does, the scan still succeeds.
The CLI prints one line on stderr for each scanner that did not complete, in
every output mode, so --json stdout stays a clean document:
! template-scanner did not complete: scan templates unavailable: ...! template-scanner stopped at its time budget; the 12 finding(s) it reported before then are keptThe JSON document (--json) also carries an engines array with one entry per
scanner, with a one-line reason when it did not complete. status is one of:
completed: the scanner ran to the end. It may have found nothing, which is a clean result. Thetemplate-scanneralso ends this way when it could not reach the target, so treat an empty result as clean only when the target was up.partial: the scanner stopped at its time budget, and the findings it reported before then are in the document.failed: the scanner produced no results (it could not start, exited with an error, wrote no report, or reached its time budget before reporting anything).
"engines": [ { "name": "web-scanner", "status": "completed" }, { "name": "template-scanner", "status": "partial", "reason": "stopped at its time budget" }]Other notices
Section titled “Other notices”A few settings change what a scanner does, and the scan says so once on stderr,
also starting with ! :
| Notice | When |
|---|---|
form login: the web-scanner signs in during the scan; the template-scanner runs unauthenticated |
A form login is set |
OpenAPI seed applies to the web-scanner only |
--openapi is set |
browser crawl skipped: ... |
--ajax-spider is set but the browser crawl cannot run (see Browser crawl) |
the web-scanner runs in a container and reaches this machine through its host-gateway address; ... |
A loopback target on Linux with a container runtime (see How the scanners run) |
Windows Defender
Section titled “Windows Defender”Microsoft Defender can flag the pinned template-scanner binary as malware and
quarantine it. This is a false positive. When it happens, the
template-scanner does not run, the scan says so on stderr, and the
web-scanner results still stand. The next scan downloads the binary again,
and Defender may remove it again.
To keep the template-scanner running, add a Defender exclusion for the CLI’s
engine cache folder, %AppData%\alertavuln\bin. From an elevated PowerShell:
Add-MpPreference -ExclusionPath "$env:APPDATA\alertavuln\bin"Exclude only that folder; on a managed machine, ask your administrator to add
the exclusion. The CLI checks every scanner it downloads against a pinned
SHA-256 checksum before installing it. Please also report the false positive to
Microsoft at microsoft.com/wdsi/filesubmission,
so the detection can be corrected for everyone. Defender can also flag a
freshly built av binary; report it the same way.
Environment variables
Section titled “Environment variables”| Variable | Description |
|---|---|
ALERTAVULN_DAST_AUTH_* |
Credentials for an authenticated scan (see av dast targets auth) |
ALERTAVULN_DAST_AJAX_SPIDER |
1 turns on the browser crawl, the same as --ajax-spider |
ALERTAVULN_DAST_TEMPLATES_DIR |
An extracted copy of the scan templates to use instead of downloading them (see Scan templates) |
Exit codes
Section titled “Exit codes”| Code | Meaning |
|---|---|
0 |
Scan completed, at least one scanner completed or returned partial findings, and no finding is at or above the --fail-on tier |
1 |
Scan failed (including when no scanner completed), authorization was refused or declined, the ownership check refused a non-loopback target (domain not verified, no DAST plan, or not logged in), or at least one finding is at or above the --fail-on tier |
See also
Section titled “See also”av dast findings- pull the consolidated DAST findings the server holds for a projectav dast targets- list a project’s registered scan targetsav dast jobs- show a project’s DAST scan-run history- Dynamic scanning (DAST) - what DAST covers, passive vs active, and hosted vs self-hosted