nuclei.md (24563B)
1 --- 2 title: "Nuclei" 3 description: "Nuclei template-based vulnerability scanning: template selection, tags, severity and workflows." 4 category: enumeration 5 tags: [enumeration, scanning, vulnerabilities] 6 tools: [Nuclei] 7 difficulty: intermediate 8 updated: "2026-08-09" 9 source: "vault:Tools/Nuclei-Cheatsheet.md" 10 --- 11 12 # Nuclei 13 14 Fast, template-driven vulnerability scanner from ProjectDiscovery (v3.x). Nuclei sends requests defined in community-maintained YAML **templates** and matches responses to confirm vulnerabilities with near-zero false positives. It supports HTTP, DNS, TCP, SSL, WHOIS, headless-browser, JavaScript and code protocols. The typical workflow is a recon pipeline — enumerate subdomains with subfinder, probe live hosts with httpx, then pipe the live URLs into `nuclei`. It clusters similar requests and runs templates in parallel, so it is fast, but that same speed can trip WAFs and rate limits on fragile CTF/lab targets — tune `-rl` and `-c` accordingly. 15 16 > **Important — Version note:** 17 > 1. Nuclei is in **active development** — flags change between minor releases. Always confirm with `nuclei -h`. 18 > 2. Requires **Go >= 1.24.2** to build from source. 19 > 3. This note targets **v3.x**. A few flag names people commonly assume do **not** exist (see Troubleshooting). 20 21 ## Quick-Reference Flag Table 22 23 | Flag (short / long) | Purpose | 24 |---|---| 25 | `-u` / `-target` | Target URL(s)/host(s), comma-separated | 26 | `-l` / `-list` | File of targets, one per line | 27 | `-im` / `-input-mode` | Input file mode: `list`, `burp`, `jsonl`, `yaml`, `openapi`, `swagger` | 28 | `-t` / `-templates` | Template file/dir to run | 29 | `-turl` / `-template-url` | Run template(s) from a URL | 30 | `-w` / `-workflows` | Run a workflow (ordered template chain) | 31 | `-et` / `-exclude-templates` | Exclude template file/dir | 32 | `-tags` / `-etags` | Include / exclude by tag | 33 | `-itags` / `-include-tags` | Force-run tags even if excluded by default | 34 | `-s` / `-severity` | Filter by severity: `info,low,medium,high,critical,unknown` | 35 | `-es` / `-exclude-severity` | Exclude by severity | 36 | `-a` / `-author` | Filter by template author | 37 | `-id` / `-eid` | Include / exclude by template ID | 38 | `-tc` / `-template-condition` | Run templates matching an expression | 39 | `-as` / `-automatic-scan` | Wappalyzer tech-detection → tag mapping | 40 | `-nt` / `-new-templates` | Only templates new in latest release | 41 | `-o` / `-output` | Write findings to file | 42 | `-j` / `-jsonl` | JSONL output | 43 | `-je` / `-json-export` | Export results as JSON file | 44 | `-jle` / `-jsonl-export` | Export results as JSONL file | 45 | `-se` / `-sarif-export` | Export results as SARIF file | 46 | `-me` / `-markdown-export` | Export results as Markdown dir | 47 | `-silent` | Findings only, no banners/logs | 48 | `-nc` / `-no-color` | Disable ANSI colour | 49 | `-v` / `-vv` | Verbose / show loaded templates | 50 | `-debug` | Show all requests + responses | 51 | `-sresp` / `-store-resp` | Save all req/resp to disk | 52 | `-rl` / `-rate-limit` | Requests per second (default 150) | 53 | `-bs` / `-bulk-size` | Hosts analysed in parallel per template (default 25) | 54 | `-c` / `-concurrency` | Templates run in parallel (default 25) | 55 | `-timeout` | Per-request timeout seconds (default 10) | 56 | `-retries` | Retries per failed request (default 1) | 57 | `-mhe` / `-max-host-error` | Errors before skipping a host (default 30) | 58 | `-p` / `-proxy` | HTTP/SOCKS5 proxy | 59 | `-H` / `-header` | Custom header/cookie `key:value` | 60 | `-sni` | TLS SNI hostname | 61 | `-i` / `-interface` | Network interface for network scans | 62 | `-sip` / `-source-ip` | Source IP for network scans | 63 | `-r` / `-resolvers` | Resolver list file | 64 | `-sr` / `-system-resolvers` | Use system DNS as fallback | 65 | `-iserver` / `-itoken` | Self-hosted Interactsh server / token | 66 | `-ni` / `-no-interactsh` | Disable OAST, skip OAST templates | 67 | `-sf` / `-secret-file` | Secrets/auth config file | 68 | `-dast` | Enable DAST (fuzzing) templates | 69 | `-ft` / `-fuzzing-type` | Override fuzz type: `replace,prefix,postfix,infix` | 70 | `-fm` / `-fuzzing-mode` | Override fuzz mode: `multiple,single` | 71 | `-validate` | Validate templates | 72 | `-up` / `-update` | Update the engine | 73 | `-ut` / `-update-templates` | Update templates | 74 | `-headless` | Enable headless-browser templates | 75 | `-page-timeout` | Seconds to wait per page in headless (default 20) | 76 77 ## Installation 78 79 ```bash 80 # 1) Go install (needs Go >= 1.24.2) — installs to $GOPATH/bin 81 go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest 82 83 # 2) Homebrew (macOS / Linux) 84 brew install nuclei 85 86 # 3) Docker 87 docker pull projectdiscovery/nuclei:latest 88 docker run --rm projectdiscovery/nuclei:latest -u https://example.com 89 90 # 4) Binary release — download from GitHub releases, unzip, move to PATH 91 # https://github.com/projectdiscovery/nuclei/releases 92 unzip nuclei_3.x.x_linux_amd64.zip 93 sudo mv nuclei /usr/local/bin/ 94 95 # Verify 96 nuclei -version 97 ``` 98 99 > **Install breakdown:** 100 > 1. **go install** — pulls latest tagged source; keep Go updated or the build fails. 101 > 2. **brew** — easiest on Kali/macOS; may lag a release behind. 102 > 3. **docker** — mount a volume for templates/output; the container has no persistent template store by default. 103 > 4. **binary** — fastest for air-gapped/offline lab boxes; grab the matching arch. 104 105 ## Template Management 106 107 Templates live in **`~/nuclei-templates/`** by default. Override with the `NUCLEI_TEMPLATES_DIR` environment variable or the `-ud` flag. On first run nuclei auto-downloads templates. 108 109 ```bash 110 # Update the nuclei engine itself 111 nuclei -up 112 nuclei -update 113 114 # Update templates to the latest release 115 nuclei -ut 116 nuclei -update-templates 117 118 # Install/update templates into a custom directory 119 nuclei -ut -ud /opt/nuclei-templates 120 121 # Disable the automatic update check (useful in CI / offline labs) 122 nuclei -u https://target -duc 123 124 # Show installed templates version 125 nuclei -tv 126 127 # List all templates matching current filters (dry run, no scan) 128 nuclei -tl -tags cve -severity critical 129 130 # List all available tags 131 nuclei -tgl 132 133 # Run only templates added in the latest templates release 134 nuclei -u https://target -nt 135 136 # Reset ALL nuclei config + data (including templates) 137 nuclei -reset 138 ``` 139 140 > **Warning — Template staleness:** 141 > 1. Run `-ut` before every engagement — new CVEs land daily. 142 > 2. `-nt` (new-templates) is great for re-scanning known targets for freshly-published CVEs only. 143 > 3. There is **no `-tlds` flag** in nuclei — see Gotchas. 144 145 ## Target Input 146 147 ```bash 148 # Single / multiple targets (comma-separated) 149 nuclei -u https://example.com 150 nuclei -u https://a.com,https://b.com 151 152 # File of targets (one per line) — this is the "target file" flag 153 nuclei -l urls.txt 154 155 # Pipe from other ProjectDiscovery tools (the classic pipeline) 156 subfinder -d example.com -silent | httpx -silent | nuclei -silent 157 158 # Read a raw HTTP request (e.g. a Burp saved request) as input 159 nuclei -l request.txt -im burp 160 161 # Scan an entire subnet for network issues 162 nuclei -u 192.168.110.0/24 163 164 # Exclude hosts from the input list 165 nuclei -l urls.txt -eh 10.10.10.5,10.10.10.6 166 ``` 167 168 > **Input breakdown:** 169 > 1. **-u / -target** — inline targets; accepts URLs, hosts, IPs, CIDRs. 170 > 2. **-l / -list** — the file-based equivalent (this is what "target file" means — there is no `-target-file` flag). 171 > 3. **stdin** — nuclei auto-reads piped input; disable with `-no-stdin`. 172 > 4. **-im burp** — parse a saved Burp/HTTP request file instead of a plain URL list. (There is no standalone `-request` flag; use `-im burp` / `-im jsonl` / `-im openapi`.) 173 174 ## Template Selection & Filtering 175 176 ```bash 177 # Run a specific template file, directory, or category 178 nuclei -u https://target -t http/cves/ 179 nuclei -u https://target -t http/cves/ -t ssl/ 180 181 # Run a template straight from a URL 182 nuclei -u https://target -turl https://example.com/my-template.yaml 183 184 # Run a workflow (ordered, conditional template chain) 185 nuclei -u https://target -w workflows/wordpress-workflow.yaml 186 187 # Exclude a template file/dir 188 nuclei -u https://target -et http/miscellaneous/ 189 190 # Tag-based include / exclude 191 nuclei -u https://target -tags cve,rce 192 nuclei -u https://target -etags dos,fuzz,intrusive 193 194 # Force-run tags even if excluded by default config 195 nuclei -u https://target -itags fuzz 196 197 # Severity include / exclude 198 nuclei -u https://target -s critical,high 199 nuclei -u https://target -es info,low 200 201 # Author filter 202 nuclei -u https://target -a pdteam,geeknik 203 204 # Template ID include / exclude (supports wildcards) 205 nuclei -u https://target -id CVE-2021-44228 206 nuclei -u https://target -id 'apache-*' -eid apache-detect 207 208 # Expression-based template condition 209 nuclei -u https://target -tc 'contains(tags,"cve") && severity=="critical"' 210 211 # Only newly-added templates 212 nuclei -u https://target -nt 213 214 # Automatic scan: Wappalyzer tech detection → maps to matching template tags 215 nuclei -u https://target -as 216 ``` 217 218 > **Tip — Filtering strategy:** 219 > 1. Start broad with `-as` to fingerprint tech, then re-run targeted `-tags`. 220 > 2. Combine filters — `-tags cve -s critical,high` is the highest-signal quick pass. 221 > 3. `-tc` (template-condition) is the power-user filter when tags/severity aren't precise enough. 222 223 ## Output 224 225 ```bash 226 # Plain text file 227 nuclei -u https://target -o findings.txt 228 229 # JSONL to stdout (best for piping into jq / tooling) 230 nuclei -u https://target -j 231 232 # Export formats (write structured report files) 233 nuclei -u https://target -je results.json # JSON 234 nuclei -u https://target -jle results.jsonl # JSONL 235 nuclei -u https://target -se results.sarif # SARIF (for GitHub code scanning) 236 nuclei -u https://target -me nuclei_report/ # Markdown dir 237 238 # Clean, quiet output 239 nuclei -u https://target -silent -nc 240 241 # Verbose / debug 242 nuclei -u https://target -v # verbose 243 nuclei -u https://target -vv # show every template loaded 244 nuclei -u https://target -debug # dump all requests + responses 245 246 # Save every request/response for later triage 247 nuclei -u https://target -sresp -srd ./resp/ 248 ``` 249 250 > **Output breakdown:** 251 > 1. **-silent + -nc** — the combo for clean logs you can paste into a report or feed to a script. 252 > 2. **-je / -jle / -se / -me** — report *exports* (write a file); **-j** just changes stdout format. 253 > 3. **-sresp / -srd** — stores raw req/resp — invaluable for confirming a finding isn't a false positive. 254 > 4. **-debug** — use when a template *should* fire but doesn't; you'll see exactly what came back. 255 256 ## Rate Limiting & Performance 257 258 ```bash 259 # Slow, polite scan for a fragile lab / CTF box 260 nuclei -u https://target -rl 20 -c 10 -bs 10 -timeout 15 -retries 2 261 262 # Requests-per-minute window (older -rlm is DEPRECATED; use -rld for duration) 263 nuclei -u https://target -rl 300 -rld 1m 264 265 # Aggressive scan for a robust target you own 266 nuclei -l urls.txt -rl 500 -c 50 -bs 50 267 268 # Tune host-error tolerance (skip dead hosts sooner) 269 nuclei -l urls.txt -mhe 10 270 nuclei -l urls.txt -no-mhe # never skip a host on errors 271 272 # Headless-browser scanning (DOM XSS, JS-heavy apps) 273 nuclei -u https://target -headless -page-timeout 30 274 nuclei -u https://target -headless -headc 5 # headless concurrency 275 ``` 276 277 | Flag | Meaning | Default | 278 |---|---|---| 279 | `-rl` | Requests per second | 150 | 280 | `-rld` | Rate-limit duration window | 1s | 281 | `-bs` | Hosts in parallel per template | 25 | 282 | `-c` | Templates in parallel | 25 | 283 | `-timeout` | Per-request timeout (s) | 10 | 284 | `-retries` | Retries per failed request | 1 | 285 | `-mhe` | Max errors before skipping host | 30 | 286 | `-headc` | Headless templates in parallel | 10 | 287 | `-page-timeout` | Wait per page in headless (s) | 20 | 288 289 > **Warning — Speed vs. stealth:** 290 > 1. High `-rl`/`-c` will trip WAFs and can crash flaky HTB/CTF services. 291 > 2. **`-headc` is headless concurrency** — do NOT confuse it with `-hc`, which is `-health-check`. 292 > 3. On labs, prefer `-rl 20 -c 10` and raise it only if the target is stable. 293 294 ## Network / Proxy 295 296 ```bash 297 # Route through Burp / a SOCKS5 pivot 298 nuclei -u https://target -p http://127.0.0.1:8080 299 nuclei -u https://target -p socks5://127.0.0.1:1080 300 301 # Custom headers / cookies injected into EVERY http request 302 nuclei -u https://target -H 'Authorization: Bearer eyJ...' 303 nuclei -u https://target -H 'Cookie: session=abc123' -H 'X-Api-Key: secret' 304 305 # TLS SNI override (virtual hosts / SNI-routed apps) 306 nuclei -u https://10.10.10.10 -sni app.internal.htb 307 308 # Custom resolvers + system fallback 309 nuclei -l urls.txt -r resolvers.txt -sr 310 311 # Network-scan interface / source IP (e.g. through a ligolo tun) 312 nuclei -u 192.168.110.0/24 -i ligolo -sip 192.168.110.10 313 ``` 314 315 > **Tip — Proxy + pivot:** 316 > 1. Send nuclei through Burp with `-p` to record traffic and manually verify hits. 317 > 2. On internal ranges reached via a Ligolo double tunnel, set `-i <tun>` so replies route back correctly. 318 > 3. `-H` applies to every HTTP template — perfect for authenticated scans (see below). 319 320 ## Interactsh / OOB 321 322 Nuclei uses Interactsh for out-of-band (OAST) detection — blind SSRF, blind SQLi, RCE with no direct response, etc. By default it uses the public servers (`oast.pro`, `oast.live`, ...). 323 324 ```bash 325 # Point at your own self-hosted Interactsh server 326 nuclei -u https://target -iserver https://oast.mydomain.com -itoken MYTOKEN 327 328 # Disable OAST entirely (skips OAST-based templates) — offline / air-gapped labs 329 nuclei -u https://target -ni 330 ``` 331 332 > **Important — When to self-host or disable:** 333 > 1. Self-host (`-iserver`/`-itoken`) when the target can't reach public OAST domains or you need to keep callbacks private. 334 > 2. Use `-ni` on isolated lab networks with **no egress** — otherwise OAST templates just time out and slow the scan. 335 336 ## Authentication 337 338 Two ways to authenticate: quick header/cookie injection, or a structured **secret file** for multi-target auth. 339 340 ```bash 341 # Quick auth via headers/cookies 342 nuclei -u https://app.target -H 'Authorization: Bearer <token>' 343 nuclei -u https://app.target -H 'Cookie: PHPSESSID=<value>' 344 345 # Structured secrets/auth file (per-domain creds, headers, cookies) 346 nuclei -l urls.txt -sf secrets.yaml 347 nuclei -l urls.txt -sf secrets.yaml -ps # prefetch secrets before scanning 348 ``` 349 350 ```yaml 351 # secrets.yaml — example static auth strategy 352 static: 353 - type: header 354 domains: 355 - app.target.htb 356 headers: 357 - key: Authorization 358 value: Bearer eyJ... 359 - type: cookie 360 domains: 361 - app.target.htb 362 cookies: 363 - key: session 364 value: abcdef123456 365 ``` 366 367 > **Auth breakdown:** 368 > 1. **-H** — simplest for a single authenticated target; header applies to all HTTP requests. 369 > 2. **-sf** — scales auth across many domains and supports header/cookie/query/basic strategies. 370 > 3. **-ps** — prefetch fires the auth flow up front so tokens are ready before templates run. 371 > 4. Header casing is preserved from the secrets file — matters for case-sensitive APIs. 372 373 ## Fuzzing / DAST Mode 374 375 Nuclei's DAST mode runs **fuzzing templates** that inject payloads into parameters (query, body, headers, path) to find injection-class bugs. The old `-fuzz` flag is deprecated — use `-dast`. 376 377 ```bash 378 # Enable DAST / fuzzing templates 379 nuclei -u 'https://target/search?q=test' -dast 380 381 # Override the fuzzing behaviour set in the template 382 nuclei -u 'https://target/?id=1' -dast -ft replace -fm single 383 384 # Control fuzz aggression (payload volume) and scope 385 nuclei -l urls.txt -dast -fa medium -cs '.*target\.htb.*' 386 387 # Show which parameters are being fuzzed (debugging) 388 nuclei -u 'https://target/?id=1' -dast -dfp 389 ``` 390 391 | Flag | Meaning | Values | 392 |---|---|---| 393 | `-dast` | Enable DAST/fuzz templates | — | 394 | `-ft` / `-fuzzing-type` | Override injection style | `replace,prefix,postfix,infix` | 395 | `-fm` / `-fuzzing-mode` | Override combination mode | `multiple,single` | 396 | `-fa` / `-fuzz-aggression` | Payload volume | `low,medium,high` (default `low`) | 397 | `-cs` / `-fuzz-scope` | In-scope URL regex | regex | 398 | `-cos` / `-fuzz-out-scope` | Out-of-scope URL regex | regex | 399 | `-dfp` / `-display-fuzz-points` | Print fuzz points | — | 400 401 > **Tip — DAST tips:** 402 > 1. Feed DAST mode URLs **with parameters** — crawl first (e.g. with `katana`) so there's something to fuzz. 403 > 2. Start at `-fa low`; raise only if you need deeper coverage — high aggression is loud. 404 > 3. Combine with `-p` (Burp proxy) to inspect and replay interesting fuzz hits. 405 406 ## Writing Custom Templates 407 408 Every template needs three parts: **`id`**, an **`info`** block, and at least one **protocol block** (usually `http`). 409 410 ```yaml 411 id: example-panel-detect 412 413 info: 414 name: Example Admin Panel Detection 415 author: netrunner 416 severity: info 417 description: Detects an exposed Example admin login panel. 418 tags: panel,exposure,example 419 420 http: 421 - method: GET 422 path: 423 - "{{BaseURL}}/admin/login" 424 425 matchers-condition: and 426 matchers: 427 - type: status 428 status: 429 - 200 430 - type: word 431 part: body 432 words: 433 - "Example Admin" 434 - "Sign in" 435 condition: or 436 437 extractors: 438 - type: regex 439 part: body 440 name: version 441 group: 1 442 regex: 443 - 'v([0-9.]+)' 444 ``` 445 446 > **Matcher types:** 447 > 1. **word** — literal string(s) in a response part. 448 > 2. **regex** — regular-expression match. 449 > 3. **status** — HTTP status code. 450 > 4. **size** — response length in bytes. 451 > 5. **dsl** — expression logic, e.g. `duration >= 5`, `status_code==200 && len(body)>1000`. 452 > 6. **binary** — hex pattern in binary responses. 453 > 7. **xpath** — XPath query against XML/HTML. 454 > 8. `matchers-condition: and|or` combines multiple matchers (default is `or`). 455 456 > **Extractor types:** 457 > 1. **regex** — pull data via regex (optional capture `group`). 458 > 2. **kval** — grab a header/cookie by key. 459 > 3. **json** — JQ-like extraction from JSON bodies. 460 > 4. **xpath** — XML/HTML extraction (optional `attribute`). 461 > 5. **dsl** — expression-based extraction, e.g. `len(body)`. 462 > 6. Extractors capture dynamic values (CSRF tokens, session IDs) for reuse in later requests. 463 464 ```yaml 465 # Variables + payloads (fuzzing / brute) skeleton 466 variables: 467 useragent: "Mozilla/5.0" 468 469 http: 470 - method: GET 471 path: 472 - "{{BaseURL}}/search?q={{injection}}" 473 headers: 474 User-Agent: "{{useragent}}" 475 attack: clusterbomb # batteringram | pitchfork | clusterbomb 476 payloads: 477 injection: 478 - "'" 479 - "' OR '1'='1" 480 - "' AND SLEEP(5)--" 481 matchers: 482 - type: dsl 483 dsl: 484 - "duration >= 5" 485 ``` 486 487 ```bash 488 # Validate a template before running it 489 nuclei -validate -t my-template.yaml 490 491 # Run your local template against a target 492 nuclei -u https://target -t ./my-template.yaml 493 494 # Run a template hosted at a URL 495 nuclei -u https://target -turl https://raw.githubusercontent.com/.../my-template.yaml 496 497 # Display a template's contents / list matches without scanning 498 nuclei -t ./my-template.yaml -td 499 nuclei -t ./my-template.yaml -tl 500 ``` 501 502 > **Warning — Template gotchas:** 503 > 1. Always `-validate` custom templates — a bad matcher silently produces no hits. 504 > 2. `part:` matters (`body`, `header`, `all`, `response`) — matching the wrong part is the #1 "why won't it fire" bug. 505 > 3. Signed/unsigned: `-dut` disables unsigned templates; your local custom ones are unsigned, so don't set `-dut` when testing them. 506 507 ## Practical Recipes 508 509 **Full recon pipeline: subfinder → httpx → nuclei** (the bread-and-butter external-recon chain): 510 511 ```bash 512 subfinder -d example.com -silent \ 513 | httpx -silent \ 514 | nuclei -silent -tags cve,exposure -s critical,high,medium -o findings.txt 515 ``` 516 517 **Polite single-target scan (HTB / CTF box)** — slow rate, moderate concurrency, retries: 518 519 ```bash 520 nuclei -u http://10.10.10.10 -rl 20 -c 10 -bs 10 -timeout 15 -retries 2 -o box_scan.txt 521 ``` 522 523 **CVE-only scan:** 524 525 ```bash 526 nuclei -u https://target -tags cve -s critical,high 527 nuclei -u https://target -t http/cves/2024/ 528 ``` 529 530 **Tech-specific scan (fingerprint first, then target):** 531 532 ```bash 533 # Auto-detect tech and map to templates 534 nuclei -u https://target -as 535 536 # Or target a known stack by tag 537 nuclei -u https://target -tags wordpress,wp-plugin 538 nuclei -u https://target -tags apache,tomcat 539 ``` 540 541 **Exposed panels & subdomain takeover:** 542 543 ```bash 544 # Login / admin panels 545 nuclei -l urls.txt -tags panel,exposure 546 547 # Subdomain takeover across a subdomain list 548 subfinder -d example.com -silent | nuclei -tags takeover -silent 549 ``` 550 551 **Scan against a saved Burp request:** 552 553 ```bash 554 # Export the request from Burp (Copy to file), then: 555 nuclei -l burp_request.txt -im burp -tags cve,injection -dast 556 ``` 557 558 ## Common One-Liners 559 560 ```bash 561 # Update engine + templates in one go 562 nuclei -up && nuclei -ut 563 564 # Quick high-signal pass on one target 565 nuclei -u https://target -tags cve -s critical,high -silent -nc 566 567 # Full pipeline, JSON export, quiet 568 subfinder -d target.com -silent | httpx -silent | nuclei -j -je out.json -silent 569 570 # Scan a list, exclude noisy/intrusive templates 571 nuclei -l urls.txt -etags dos,fuzz,intrusive -es info -o clean.txt 572 573 # Log4Shell / specific CVE across many hosts 574 nuclei -l urls.txt -id CVE-2021-44228 -silent 575 576 # Network subnet sweep through a ligolo tun 577 nuclei -u 192.168.110.0/24 -i ligolo -tags network -o net.txt 578 579 # DAST fuzz a parameterised URL through Burp 580 nuclei -u 'https://target/?id=1' -dast -p http://127.0.0.1:8080 -dfp 581 582 # Authenticated scan with a bearer token, save all responses 583 nuclei -u https://app.target -H 'Authorization: Bearer TOKEN' -sresp -srd ./resp/ 584 585 # Dry-run: list which templates a filter would run 586 nuclei -tl -tags cve -s critical 587 588 # Re-scan known target for only newly-released templates 589 nuclei -u https://target -nt -silent 590 ``` 591 592 ## Troubleshooting & Gotchas 593 594 > **Flags that don't exist / are easy to confuse:** 595 > 1. **`-tlds`** — not a nuclei flag. Nuclei doesn't take a TLD list; scope is controlled by targets, `-eh`, and fuzz scope regex (`-cs`/`-cos`). 596 > 2. **`-target-file`** — not a flag. The file-of-targets flag is **`-l` / `-list`**. 597 > 3. **`-request`** — not a flag. Parse raw HTTP/Burp requests with **`-im burp`** (or `-im jsonl`/`-im openapi`). 598 > 4. **`-hc`** — this is **`-health-check`**, *not* headless concurrency. Headless concurrency is **`-headc`**. 599 > 5. **`-json`** — the JSON stdout flag is **`-j` / `-jsonl`**; file exports are **`-je`/`-jle`/`-se`/`-me`**. 600 > 6. **`-template-url`** is **`-turl`** (not `-tu`). 601 602 > **Common runtime issues:** 603 > 1. **WAF trips / blocked mid-scan** → lower `-rl` and `-c`; add `-p` to watch the block in Burp. 604 > 2. **False positives** → confirm with `-sresp`/`-debug`, then exclude with `-eid <id>`. 605 > 3. **Stale results / missing new CVEs** → run `-ut`; use `-nt` to hit only fresh templates. 606 > 4. **Noisy logs** → add `-silent -nc` for clean, scriptable output. 607 > 5. **OAST templates hang on isolated labs** → add `-ni` to disable Interactsh. 608 > 6. **JS/DOM-heavy app finds nothing** → try `-headless` (root on Linux disables the Chrome sandbox). 609 > 7. **Host skipped early** → raise `-mhe` or use `-no-mhe` for flaky lab services. 610 611 ## Lessons Learned 612 613 1. **Confirm flags against `nuclei -h`, not memory** — several "obvious" flags (`-tlds`, `-target-file`, `-request`) don't exist, and short aliases collide (`-hc` ≠ headless). 614 2. **Update templates before every scan** — nuclei's value is the community template feed; a stale feed misses this week's CVEs. Use `-nt` to re-check known targets cheaply. 615 3. **Tune rate before scanning labs** — default `-rl 150` will hammer a fragile HTB/CTF box; `-rl 20 -c 10` is a safe starting point. 616 4. **The `subfinder → httpx → nuclei` pipeline is the standard external-recon workflow** — pipe live hosts in via stdin and let nuclei do the detection. 617 5. **Verify hits before reporting** — pair `-sresp`/`-debug` with a Burp proxy (`-p`) to rule out false positives, then `-eid` to suppress known noise. 618 619 ## References 620 621 - Nuclei Overview — https://docs.projectdiscovery.io/tools/nuclei/overview 622 - Nuclei Installation — https://docs.projectdiscovery.io/tools/nuclei/install 623 - Nuclei Command-Line Flags — https://docs.projectdiscovery.io/tools/nuclei/running 624 - Nuclei GitHub — https://github.com/projectdiscovery/nuclei 625 - Nuclei Templates — https://github.com/projectdiscovery/nuclei-templates 626 - Matchers Reference — https://docs.projectdiscovery.io/templates/reference/matchers 627 - Extractors Reference — https://docs.projectdiscovery.io/templates/reference/extractors 628 - Interactsh (OAST) — https://github.com/projectdiscovery/interactsh 629 - subfinder — https://github.com/projectdiscovery/subfinder 630 - httpx — https://github.com/projectdiscovery/httpx