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.
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:
| Phase | What goes on the wire | Prod-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 scan | Response-only analysis; no extra requests beyond the crawl. | Yes. |
| Active scan | Injection 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. |
Recommended prod-safe config
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:
- You've isolated a staging-equivalent tenant in prod (separate org/workspace) that the scan account can only see.
- Writes from that tenant can't leak to customer-visible state.
- You have a rollback plan (database snapshot, feature flag) and a person on call.
Even then:
scan.attack_strength: "low"— notmedium/high/insane.scan.max_payloads: 25— cap blast radius per endpoint.scan.active_delay_ms: 200— rate-limit yourself.- Narrow
scan.http_methodsto["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 raisescan.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
- Passive vs active scanning — what each mode actually does.
- CI/CD integration — wire prod scans to a nightly schedule.
- Main troubleshooting — if a prod scan misbehaves.