This guide provides an in-depth look at all components that make up a Nuclei template, from required fields to advanced configurations.
Template hierarchy
A Nuclei template follows this structure:
id: template-identifier
info:
# Metadata block
variables:
# Template-level variables
constants:
# Immutable values
flow: |
# Execution flow logic (optional)
[protocol]:
# One or more protocol blocks
- # Request definition
matchers:
# Match conditions
extractors:
# Data extraction
self-contained: false
stop-at-first-match: false
Required sections
Template ID
Unique identifier for the template across all templates.Rules:
- Use lowercase letters, numbers, and hyphens
- Start with a letter
- Be descriptive but concise
- Use CVE ID format for CVE templates:
CVE-2021-12345
- Use technology prefixes:
wordpress-, jenkins-, apache-
Examples:id: CVE-2021-44228
id: wordpress-xmlrpc-listmethods
id: nginx-version-detect
Info block
Contains all template metadata and classification information.
Required info fields
info:
name: Human-Readable Template Name
author: researcher1,researcher2
severity: critical
Purpose: Describes what the template detectsGuidelines:
- Use title case
- Be specific but not verbose
- Mention the vulnerability type
- Include product name if relevant
Examples:
- “Apache Log4j Remote Code Execution”
- “Exposed Git Repository”
- “WordPress Plugin SQL Injection”
Purpose: Credits the template creator(s)Format: Comma-separated usernames (no spaces)author: pdteam
author: researcher1,researcher2,researcher3
Purpose: Indicates the risk levelValues:
info - Informational, no direct security impact
low - Minor security issues
medium - Moderate vulnerabilities
high - Serious vulnerabilities
critical - Severe, immediate risk
Optional info fields
Description
References
Tags
Classification
Metadata
Remediation
info:
description: |
Detailed explanation of the vulnerability,
its impact, and detection methodology.
Can be multi-line.
Use pipe (|) for multi-line descriptions.info:
reference:
- https://nvd.nist.gov/vuln/detail/CVE-2021-12345
- https://blog.researcher.com/vulnerability-writeup
- https://github.com/project/security/advisories/1234
List of URLs with vulnerability details, advisories, or writeups.info:
tags: cve,cve2021,rce,apache,log4j,critical
Comma-separated keywords for filtering and searching (lowercase, no spaces).info:
classification:
cvss-metrics: CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
cvss-score: 9.8
cve-id: CVE-2021-44228
cwe-id: CWE-502
epss-score: 0.97
cpe: cpe:2.3:a:apache:log4j:2.14.1:*:*:*:*:*:*:*
Standardized vulnerability classification data.info:
metadata:
max-request: 3
shodan-query: 'http.title:"Admin Panel"'
fofa-query: 'app="WordPress"'
verified: true
Custom key-value pairs for additional context.info:
remediation: |
1. Update to version X.Y.Z or later
2. Apply security patches from vendor
3. Implement additional security controls
Steps to fix or mitigate the vulnerability.
Protocol blocks
Every template needs at least one protocol section defining the requests to send.
Supported protocols
HTTP
Web application testing
DNS
DNS queries and zone enumeration
Network/TCP
Raw TCP connections
SSL/TLS
Certificate and SSL checks
WebSocket
WebSocket connections
WHOIS
Domain registration data
JavaScript
Custom protocol logic
Code
Execute code snippets
File
Local file system scanning
Basic protocol structure
http:
- method: GET
path:
- "{{BaseURL}}/path"
matchers:
- type: word
words:
- "success"
Each protocol can have multiple requests:
http:
- # Request 1
method: GET
path:
- "{{BaseURL}}/api/v1"
- # Request 2
method: POST
path:
- "{{BaseURL}}/api/v2"
Variables and constants
Variables
Define dynamic values that can use DSL functions and are evaluated at runtime.variables:
random_id: "{{rand_int(100000, 999999)}}"
encoded_host: "{{base64(Host)}}"
timestamp: "{{unix_time()}}"
Use in requests:http:
- path:
- "{{BaseURL}}/api?id={{random_id}}"
Constants
Define static values that never change.constants:
api_version: "v1"
default_user: "admin"
max_retries: 3
Matchers
Define conditions that must be met for a template to report a match.
Matcher types
Word
Regex
Status
Size
DSL
Binary
matchers:
- type: word
words:
- "admin panel"
- "dashboard"
condition: or
part: body
Searches for exact strings in the response.matchers:
- type: regex
regex:
- "([a-zA-Z0-9_-]+\.)*example\.com"
part: body
Uses regular expressions for pattern matching.matchers:
- type: status
status:
- 200
- 301
- 302
Matches HTTP status codes.matchers:
- type: size
size:
- 1234
- 5678
Matches response body size in bytes.matchers:
- type: dsl
dsl:
- "status_code == 200"
- "contains(body, 'admin')"
- "len(body) > 1000"
condition: and
Uses Nuclei’s DSL for complex logic.matchers:
- type: binary
binary:
- "504B0304" # ZIP header
- "89504E47" # PNG header
part: body
Matches binary patterns (hex encoded).
Matcher conditions
matchers-condition: and # ALL matchers must match
matchers:
- type: status
status:
- 200
- type: word
words:
- "vulnerable"
matchers-condition: or # ANY matcher can match (default)
matchers:
- type: word
words:
- "admin"
- type: word
words:
- "administrator"
Extract data from responses for reporting or use in subsequent requests.
Regex
KVal
JSON
XPath
DSL
extractors:
- type: regex
name: api_key
regex:
- 'api[_-]?key["\']?\s*[:=]\s*["\']?([a-zA-Z0-9-_]+)'
group: 1
Extract using regular expression groups.extractors:
- type: kval
kval:
- "Set-Cookie"
- "Authorization"
Extract header values by key name.extractors:
- type: json
json:
- ".data.token"
- ".user.id"
Extract from JSON responses using JSON path.extractors:
- type: xpath
xpath:
- "/html/head/title"
- "//input[@type='hidden']/@value"
Extract from HTML/XML using XPath.extractors:
- type: dsl
dsl:
- "to_lower(body)"
- "len(all_headers)"
Extract computed values using DSL.
extractors:
- type: regex
name: csrf_token
internal: true # Don't show in output
regex:
- 'csrf_token"\s*value="([^"]+)"'
group: 1
Use in subsequent request:
http:
- # Request 1 - extract token
method: GET
path:
- "{{BaseURL}}/login"
extractors:
- type: regex
name: csrf_token
internal: true
regex:
- 'name="csrf_token" value="([^"]+)"'
group: 1
- # Request 2 - use token
method: POST
path:
- "{{BaseURL}}/login"
body: "username=admin&password=test&csrf_token={{csrf_token}}"
Global options
Self-contained
Template doesn’t require external input; URLs are included in the template.id: specific-target-check
self-contained: true
http:
- raw:
- |
GET http://specific-target.com/api HTTP/1.1
Host: specific-target.com
Stop at first match
Stop template execution after first successful match.stop-at-first-match: true
http:
- path:
- "{{BaseURL}}/admin"
- "{{BaseURL}}/administrator"
- "{{BaseURL}}/wp-admin"
Stops after finding the first accessible admin panel.
Flow control
Advanced execution control using JavaScript-like syntax.flow: |
http("probe");
if (template["probe_status"] == true) {
http("exploit");
}
See Flow Control for details.
Multi-protocol templates
Combine multiple protocols in one template:
id: multi-protocol-check
info:
name: DNS and HTTP Combined Check
author: researcher
severity: info
dns:
- name: "{{FQDN}}"
type: A
matchers:
- type: word
words:
- "IN\tA"
http:
- method: GET
path:
- "{{BaseURL}}"
matchers:
- type: status
status:
- 200
Request chaining
Pass data between requests:
http:
- method: GET
path:
- "{{BaseURL}}/api/session"
extractors:
- type: json
name: session_id
internal: true
json:
- ".session.id"
- method: GET
path:
- "{{BaseURL}}/api/data"
headers:
X-Session-ID: "{{session_id}}"
matchers:
- type: word
words:
- "authenticated"
Part definitions
Each protocol exposes different parts for matching/extraction:
HTTP parts
body - Response body (default)
header - Response headers
all - Headers + body
status_code - HTTP status code
content_length - Response length
raw - Complete raw response
DNS parts
raw - Full DNS response (default)
answer - Answer section
question - Question section
ns - Nameserver section
extra - Additional section
Network parts
data - Received data (default)
raw - Complete interaction
request - Sent request
Template examples
id: admin-panel-detect
info:
name: Admin Panel Detection
author: researcher
severity: info
http:
- method: GET
path:
- "{{BaseURL}}/admin"
matchers:
- type: word
words:
- "admin panel"
- "administrator"
condition: or
Next steps
Protocol guides
Deep dive into specific protocols
Matchers reference
Complete matcher documentation
Extractors reference
All extractor types explained
Helper functions
DSL function reference