Skip to main content

Scanning production safely

DAST is a write-path tool by default. Left on defaults and pointed at production, the scanner will submit forms, mutate records, and trigger side-effects. This page is the single reference for running against production without breaking it.

Default: scan staging, not prod

Run DAST against a staging or pre-prod environment whenever possible. The rest of this page assumes you've decided, with eyes open, that you must scan production.

What the scanner actually sends

Understand the traffic profile before you flip this on in prod:

PhaseWhat goes on the wireProd-safe?
Crawl (standard / hybrid)GET requests on every discoverable link; follows redirects; loads JS and clicks interactive elements.Mostly — same as a logged-in user browsing.
Crawl (ai / hybrid with ai_form_filling)LLM-filled form submissions (POST, PUT, PATCH). Can create accounts, comments, orders.No — turn off ai_form_filling for prod.
Passive scanResponse-only analysis; no extra requests beyond the crawl.Yes.
Active scanInjection payloads (XSS, SQLi, SSRF, path traversal, command injection, …) in query strings, bodies, headers, and paths. Sends many requests per endpoint.No — disable active testing in prod.
CVE scan (cve.js, cve.dom)Fingerprinting requests and DOM inspection only.Yes.

Passive + CVE only, no active injection, no AI form filling, explicit exclude list:

# levo-dast.yml
version: "1"
name: "acme-webapp"
env: "production"

target:
url: "https://app.example.com"
ignore_third_party: true
exclude_domains:
- "billing.example.com" # never touch payment flows
- "admin.example.com"

crawl:
type: "standard" # not ai / hybrid
ai_form_filling: false
max_depth: 3
max_pages: 150

scan:
enable_passive: true
enable_active: false # the load-bearing line
enable_websocket: false

cve:
js: true
dom: true

reporting:
output: "sarif"
output_file: "reports/prod.sarif"
severity: "medium"

Run as a read-only account:

shadownet scan --config levo-dast.yml --token "$READONLY_API_TOKEN"

If you must run active tests in prod

Only if all of the following are true:

  1. You've isolated a staging-equivalent tenant in prod (separate org/workspace) that the scan account can only see.
  2. Writes from that tenant can't leak to customer-visible state.
  3. You have a rollback plan (database snapshot, feature flag) and a person on call.

Even then:

  • scan.attack_strength: "low" — not medium/high/insane.
  • scan.max_payloads: 25 — cap blast radius per endpoint.
  • scan.active_delay_ms: 200 — rate-limit yourself.
  • Narrow scan.http_methods to ["GET", "POST"] unless you have a specific reason.
  • Disable categories that mutate: path_traversal, command_injection, and anything else you haven't reviewed.
  • Run off-peak and watch your error-rate dashboard live.

Scan account hygiene

  • Dedicated service account — never a human's credentials.
  • Least privilege — the account sees only the endpoints you want tested.
  • No prod admin role — even "read-only admin" often has write-shaped endpoints (e.g., DELETE /sessions/:id).
  • Rotate the token after every scan, or put it on a short TTL.

Rate-limit and WAF coordination

  • Add the scanner's source IP (or your worker's egress IP) to an allowlist.
  • Tell your WAF vendor a scan is running — some detect payloads as an attack and auto-block the source.
  • If you hit rate limits, lower scan.max_payloads, crawl.max_pages, and raise scan.active_delay_ms.

Running from a worker in prod

If you can't open your prod network to Levo's cloud runner, deploy a Kubernetes worker or a Docker worker inside the prod VPC. It pulls jobs outbound, so no inbound firewall change is needed.

Next

Was this page helpful?