Skip to content

Expose nuclei's newer template-selection options - #3479

Merged
liquidsec merged 5 commits into
devfrom
nuclei-template-filters
Oct 21, 2026
Merged

liquidsec merged 5 commits into
devfrom
nuclei-template-filters

Conversation

@liquidsec

Copy link
Copy Markdown
Contributor

Closes #3478.

The nuclei module was written in 2022, when -severity was essentially the only way to narrow the template set. This exposes what ProjectDiscovery has added since, and fixes budget mode.

Template selection

Nine passthrough options that sit alongside mode rather than adding new mode values, so they compose. nuclei intersects its filters, so profile: recommended plus severity: critical gives you the templates satisfying both.

option flag option flag
profile -tp exclude_severity -es
template_condition -tc protocol_types -pt
new_templates -nt include_tags -itags
new_templates_versions -ntv template_ids -id
exclude_ids -eid

-tc opens the most up: it filters on template metadata that didn't exist when this module was written, including epss_score, cvss_score, max_request, cve_id, vendor and product.

Two presets: nuclei-recommended (ProjectDiscovery's curated profile, which carries a maintained list of known-FP template ids that updates with the template tree) and nuclei-new (latest templates release only).

Validation

severity, exclude_severity and protocol_types are validated against nuclei's enums at preset-validation time instead of failing partway into a scan. severity wasn't validated at all before.

Those lists are hardcoded, since module Config bodies are exec'd without module globals. TestNucleiEnumDrift parses nuclei -h and asserts every value the binary advertises still passes validation, so a version bump that changes them fails here rather than in the field.

profile accepts a built-in profile id or a path to a profile file. template_condition gets a pre-flight match count, because nuclei treats an unrecognized field name as a non-match rather than an error, so a typo would otherwise select nothing and report success.

Budget mode

Nothing in nuclei replaces budget mode. metadata.max-request caps requests per template; budget mode caps them per host, by selecting templates whose paths all come from the N most common paths in the tree so nuclei's clustering merges them.

Two selection bugs:

  • valid was initialized once per template, but the path loop runs per request block and never reset it.
  • A template was accepted when any single block was in budget, while nuclei still ran its other blocks. 39 templates leak this way in the current tree.

This is a user-visible change. budget: 10, which is what nuclei-budget.yml ships, goes from 1,581 templates / 134 requests per host to 1,477 / 15. Roughly the same coverage for a tenth of the traffic, and budget: N now actually means N.

Separately, the yaml.safe_load sweep over all 13,510 templates was 35.2s, blocking, on the event loop, and reran every scan. It's now cached as JSON keyed on the installed templates version, and runs in run_in_executor_mp on a miss. 34.7s to 0.01s warm.

Note

docs/scanning/advanced.md is deliberately untouched. The docs generator rewrites its argparse block differently depending on local Python version, and that churn isn't part of this change.

Add nine passthrough options that compose alongside `mode` rather than
adding new `mode` values: profile, template_condition, new_templates,
new_templates_versions, exclude_severity, protocol_types, include_tags,
template_ids, exclude_ids.

Validate severity, exclude_severity and protocol_types against nuclei's
enums at preset-validation time, with a test that pins those lists
against what the binary advertises.

Fix two budget mode selection bugs that let templates run request blocks
outside the budget, and cache the template parse on the installed
templates version instead of repeating it every scan.

Add nuclei-recommended and nuclei-new presets.
@liquidsec liquidsec self-assigned this Oct 1, 2026
@liquidsec liquidsec added this to the BBOT 3.1 - violent_barbara milestone Oct 1, 2026
@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 90.14778% with 20 lines in your changes missing coverage. Please review.
✅ Project coverage is 91%. Comparing base (9be1ae9) to head (b02d0b6).
⚠️ Report is 1 commits behind head on dev.

Files with missing lines Patch % Lines
bbot/modules/nuclei.py 84% 20 Missing ⚠️
Additional details and impacted files
@@          Coverage Diff           @@
##             dev   #3479    +/-   ##
======================================
- Coverage     91%     91%    -0%     
======================================
  Files        465     465            
  Lines      50015   50134   +119     
======================================
+ Hits       45142   45244   +102     
- Misses      4873    4890    +17     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

📊 Performance Benchmark Report

Comparing dev (baseline) vs nuclei-template-filters (current)

📈 Detailed Results (All Benchmarks)

📋 Complete results for all benchmarks - includes both significant and insignificant changes

🧪 Test Name 📏 Base 📏 Current 📈 Change 🎯 Status
Bloom Filter Dns Mutation Tracking Performance 3.03ms 3.01ms -0.8% ⚪ ✅
Bloom Filter Large Scale Dns Brute Force 12.44ms 11.70ms -5.9% ⚪ ✅
Large Closest Match Lookup 252.94ms 262.92ms +3.9% ⚪ ✅
Realistic Closest Match Workload 139.60ms 140.19ms +0.4% ⚪ ✅
Event Memory Medium Scan 1402 B/event 1403 B/event +0.1% ⚪ ✅
Event Memory Large Scan 1527 B/event 1527 B/event +0.0% ⚪ ✅
Event Validation Full Scan Startup Small Batch 319.38ms 326.85ms +2.3% ⚪ ✅
Event Validation Full Scan Startup Large Batch 407.14ms 413.83ms +1.6% ⚪ ✅
Make Event Autodetection Small 16.45ms 16.08ms -2.3% ⚪ ✅
Make Event Autodetection Large 161.43ms 160.46ms -0.6% ⚪ ✅
Make Event Explicit Types 6.72ms 6.65ms -1.1% ⚪ ✅
Excavate Single Thread Small 3.028s 3.021s -0.2% ⚪ ✅
Excavate Single Thread Large 7.715s 7.803s +1.1% ⚪ ✅
Excavate Parallel Tasks Small 3.232s 3.176s -1.7% ⚪ ✅
Excavate Parallel Tasks Large 4.990s 4.897s -1.9% ⚪ ✅
Intercept Throughput Small 799.92ms 786.00ms -1.7% ⚪ ✅
Intercept Throughput Medium 918.87ms 777.52ms -15.4% 🟢🟢 🚀
Dns Throughput Quiet 1.988s 2.038s +2.5% ⚪ ✅
Dns Throughput Loaded 1.503s 1.413s -5.9% ⚪ ✅
Dns Throughput Inherited 1.754s 1.915s +9.2% ⚪ ✅
Is Ip Performance 1.73ms 1.72ms -0.5% ⚪ ✅
Make Ip Type Performance 163.77µs 150.00µs -8.4% ⚪ ✅
Mixed Ip Operations 1.80ms 1.79ms -0.7% ⚪ ✅
Memory Use Web Crawl 1.2 MB 1.2 MB +0.0% ⚪ ✅
Memory Use Subdomain Enum 28.3 MB 28.3 MB +0.0% ⚪ ✅
Memory Use Deep Chain 5.0 MB 5.0 MB +0.0% ⚪ ✅
Memory Use Parallel Chains 12.8 MB 11.6 MB -10.0% ⚪ ✅
Scan Throughput 100 2.162s 2.317s +7.1% ⚪ ✅
Scan Throughput 1000 14.076s 14.618s +3.8% ⚪ ✅
Typical Queue Shuffle 4.70µs 4.22µs -10.2% 🟢🟢 🚀
Priority Queue Shuffle 20.87µs 21.53µs +3.2% ⚪ ✅

🎯 Performance Summary

+ 2 improvements 🚀
  29 unchanged ✅

🔍 Significant Changes (>10%)

  • Intercept Throughput Medium: 15.4% 🚀 faster
  • Typical Queue Shuffle: 10.2% 🚀 faster

🐍 Python Version 3.11.17

@singlerider singlerider linked an issue Oct 3, 2026 that may be closed by this pull request
@liquidsec
liquidsec marked this pull request as ready for review October 15, 2026 19:18
en0f
en0f previously approved these changes Oct 20, 2026
@liquidsec
liquidsec merged commit c9f5e0a into dev Oct 21, 2026
19 checks passed
@liquidsec
liquidsec deleted the nuclei-template-filters branch October 21, 2026 15:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose nuclei's newer template-selection options

2 participants