levo-dast.yml schema reference
Every top-level key in levo-dast.yml, grouped by concern. Unknown keys cause a load error (extra = "forbid"), so typos surface immediately.
Top-level keysโ
| Key | Purpose |
|---|---|
version | Schema version. Always "1" for now. |
name | Logical scan / app name used in reports. |
target | URL and scope (capture / exclude domains). |
crawl | Crawler type, bounds, and crawl timeout. |
auth | Strategy + non-secret auth fields. |
scan | Phase toggles, injection controls, timeouts, and per-category active-test flags. |
cve | JS, DOM, and nuclei CVE checks. |
chatbot | Inline chatbot testing. |
ai | LLM provider (key stays in env). |
satellite | On-prem traffic export. |
app.*, vulnerabilities.*, timeouts.*, env.*, and levo.* are not top-level blocks โ the loader rejects them. version and name are the only top-level scalars; everything else (target, crawl, auth, scan, cve, chatbot, ai, satellite) is a nested block. Active-test categories nest inside scan.active_testing_categories; timeouts nest inside scan and crawl; Levo IDs are secrets and come from CLI/env.
version, nameโ
version: "1"
name: "acme-webapp"
| Field | Type | Default | Notes |
|---|---|---|---|
version | string | required | Schema version. |
name | string | required | Logical name used in reports. |
The Levo env-id (which environment a scan reports findings against) is a Levo identity value and comes from --env-id / LEVOAI_ENV_ID, not from this file.
targetโ
target:
url: "https://app.example.com"
start_page: "/login"
ignore_third_party: true
capture_domains:
- "*.example.com"
exclude_domains:
- "analytics.example.com"
| Field | Type | Default | Notes |
|---|---|---|---|
url | string | required | Base URL. Domain must be an owned domain. |
start_page | string | / | Path to start crawling from. |
ignore_third_party | bool | true | Skip hosts outside your org. |
capture_domains | string[] | [] | Extra in-scope hosts (glob patterns). |
exclude_domains | string[] | [] | Hosts to skip. |
crawlโ
crawl:
type: "hybrid"
max_depth: 5
max_pages: 200
max_clicks_per_page: 30
max_global_clicks: 1000
ai_form_filling: true
ai_form_policy: "moderate"
timeout: 900
| Field | Type | Default | Notes |
|---|---|---|---|
type | enum | standard | standard ยท ai ยท hybrid ยท legacy. |
max_depth | int | 3 | Link-depth cap. |
max_pages | int | 100 | Upper bound on unique pages. |
max_clicks_per_page | int | 20 | AI-assisted click budget per page. |
max_global_clicks | int | 500 | Click budget across the scan. |
ai_form_filling | bool | false | Let an LLM fill unknown forms. |
ai_form_policy | enum | moderate | conservative ยท moderate ยท aggressive. |
timeout | int | 900 | Crawl phase timeout, seconds. |
authโ
auth:
strategy: "form"
username: "${SCAN_USERNAME}"
login_url: "https://app.example.com/login"
wait_for_mfa: false
headers:
- "X-Scan-Source: shadownet"
# custom_instructions: "Click the 'Continue with email' button first."
# session_file: "session.json" # only for strategy: session_transplant
| Field | Type | Default | Notes |
|---|---|---|---|
strategy | enum | none | none ยท form ยท token ยท ai ยท session_transplant. |
username | string | โ | Non-secret half of form auth. |
login_url | string | โ | Required for form and most ai flows. |
wait_for_mfa | bool | false | Pause for MFA in interactive mode. |
headers | string[] | [] | Extra request headers. Non-secret only. CR/LF rejected. |
custom_instructions | string | โ | Free-text guidance surfaced to the LLM during AI-guided login (strategy: ai only). Max 4000 chars. |
session_file | string | โ | Relative path to a Levo-extension-exported session JSON. Pairs with strategy: session_transplant. Equivalent to --auth-session-file. |
Strategiesโ
| Strategy | When to pick it |
|---|---|
none | Public site, or you want crawl-only. |
form | Username/password login via a normal form. |
token | API with Authorization: Bearer โฆ. |
ai | LLM walks the login flow โ useful for unusual UIs, SSO that fits in a single browser. |
session_transplant | You have a session.json exported from the Levo browser extension. Scanner skips auth entirely and reuses your cookies + storage. |
password, token, raw cookie values, and local_storage_b64 are rejected. Use --password, --token, --auth-session-file, or env vars (SCAN_PASSWORD, SCAN_TOKEN, โฆ).
scanโ
scan:
enable_passive: true
enable_active: true
enable_websocket: true
enable_graphql: true
enable_ai: false
attack_strength: "medium"
max_payloads: 100
active_delay_ms: 50
http_methods: ["GET", "POST", "PUT", "DELETE"]
inject_locations: ["query", "body", "header", "path"]
depth: "thorough"
tech_aware: true
timeout: 3600
test_timeout: 30
probe_timeout: 15
active_testing_categories:
xss: true
sqli: true
path_traversal: true
ssrf: true
xxe: true
command_injection: true
open_redirect: true
csrf: true
idor: true
| Field | Type | Default | Notes |
|---|---|---|---|
enable_passive | bool | true | Response analysis only (prod-safe). |
enable_active | bool | true | Sends injection payloads. |
enable_websocket | bool | true | Test WS/WSS endpoints. |
enable_graphql | bool | true | Introspect and fuzz GraphQL. |
enable_ai | bool | false | LLM triage of findings. |
attack_strength | enum | medium | low ยท medium ยท high ยท insane. |
max_payloads | int | 50 | Active payloads per endpoint. |
active_delay_ms | int | 0 | Throttle between payloads. |
http_methods | string[] | ["GET","POST","PUT"] | Verbs to exercise. |
inject_locations | string[] | ["query","body","header","cookie","path"] | Injection points. |
depth | enum | smart | smart (default) ยท thorough. |
tech_aware | bool | true | Skip tests irrelevant to detected stack. |
timeout | int | 3600 | Overall scan budget, seconds. |
test_timeout | int | 30 | Per-test timeout, seconds. |
probe_timeout | int | 15 | Per-probe timeout, seconds. |
active_testing_categories | map | all true | Per-category toggles; only applied when enable_active: true. Omit categories to keep them on. |
scan.active_testing_categoriesโ
Nested map controlling individual active-test categories:
| Key | Default | Tests |
|---|---|---|
xss | true | Cross-site scripting (reflected, stored). |
sqli | true | SQL injection (error-based, time-based, union). |
path_traversal | true | ../ / LFI / directory traversal. |
ssrf | true | Server-side request forgery. |
xxe | true | XML external entity. |
command_injection | true | OS command injection. |
open_redirect | true | Unvalidated redirects. |
csrf | true | CSRF token absence / weakness. |
idor | true | Insecure direct object reference. |
cveโ
cve:
js: true
dom: true
nuclei_templates: "cves/,exposures/"
| Field | Type | Default | Notes |
|---|---|---|---|
js | bool | false | JavaScript library CVE scanning. |
dom | bool | false | DOM-based XSS and client injection. |
nuclei_templates | string | โ | Nuclei template paths (comma-separated). |
chatbotโ
chatbot:
inline: true
test_timeout: 120
max_count: 5
| Field | Type | Default | Notes |
|---|---|---|---|
inline | bool | false | Test embedded chatbot widgets. |
test_timeout | int | 60 | Per-turn timeout (seconds). |
max_count | int | 3 | Cap on detected chatbots to test. |
aiโ
ai:
provider: "anthropic"
| Field | Type | Default | Notes |
|---|---|---|---|
provider | enum | anthropic | anthropic ยท openai. API key in env (ANTHROPIC_API_KEY / OPENAI_API_KEY). |
satelliteโ
See Install Satellite for how to stand one up.
satellite:
enabled: true
url: "https://satellite.levo.ai"
span_buffer_size: 1000
flush_interval: 10
| Field | Type | Default | Notes |
|---|---|---|---|
enabled | bool | false | Route scan traffic through a Levo Satellite. |
url | string | โ | Satellite HAProxy URL. |
span_buffer_size | int | 1000 | In-memory span buffer. |
flush_interval | int | 10 | Flush interval, seconds. |
Secrets โ never in YAMLโ
These must come from CLI flags or env vars, not the file:
| Category | Keys / env vars |
|---|---|
| Levo identity | --org-id / LEVOAI_ORG_ID, --workspace-id / LEVOAI_WORKSPACE_ID, --env-id / LEVOAI_ENV_ID, --app-id / LEVOAI_APP_ID, LEVOAI_AUTH_KEY |
| Auth creds | --password / SCAN_PASSWORD, --token / SCAN_TOKEN, raw cookies, local_storage_b64 |
| LLM / third-party | ANTHROPIC_API_KEY, OPENAI_API_KEY, CAPSOLVER_API_KEY, INTERACTSH_SERVER_URL, INTERACTSH_SERVER_AUTH_TOKEN |
Validation errorsโ
The loader reports errors with the YAML path of the offending field:
levo-dast.yml:scan.attack_strength: value 'extreme' is not a valid enum
(expected: low, medium, high, insane)
Typos surface the same way (thanks to extra = "forbid"):
levo-dast.yml: unknown field 'scann' at top level
(did you mean 'scan'?)
Secret keys are rejected with an actionable hint:
levo-dast.yml:auth.password: secrets not allowed in YAML
โ use --password or SCAN_PASSWORD env var
Nextโ
- Examples & recipes.
- CLI reference for the matching flags.