Skip to main content
Nuclei templates use YAML (Yet Another Markup Language) for defining vulnerability checks. This page covers the syntax fundamentals and conventions used in template development.

YAML basics

Structure

YAML uses indentation (spaces, not tabs) to define structure:
parent:
  child: value
  another_child:
    nested: data
Never use tabs for indentation. YAML requires spaces only. Most editors can be configured to insert spaces when you press Tab.

Data types

Strings

# Unquoted
name: Simple string value

# Quoted (use for special characters)
name: "String with: colons"
name: 'String with "quotes"'

# Multi-line
description: |
  This is a multi-line
  string that preserves
  line breaks

Numbers and booleans

port: 443
severity_score: 9.8
enabled: true
disabled: false

Lists

# Dash notation
tags:
  - cve
  - rce
  - critical

# Inline notation
status: [200, 301, 302]

Maps/dictionaries

info:
  name: Template Name
  author: researcher
  severity: high

Template structure

Required fields

Every template must include:
id
string
required
Unique identifier for the template. Use lowercase with hyphens.
id: apache-log4j-rce
info
object
required
Metadata block describing the template.
info:
  name: Apache Log4j Remote Code Execution
  author: pdteam
  severity: critical
[protocol]
array
required
One or more protocol request definitions (http, dns, tcp, etc.).
http:
  - method: GET
    path:
      - "{{BaseURL}}"

Info block fields

The info section contains template metadata:
info:
  name: Human-readable template name
  author: username1,username2
  severity: info|low|medium|high|critical
  description: Detailed explanation of what is detected
  reference:
    - https://example.com/advisory
    - https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2021-1234
  tags: cve,cve2021,rce,apache
  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-1234
    cwe-id: CWE-502
  metadata:
    max-request: 2
    shodan-query: http.title:"Apache Tomcat"
  remediation: Apply the latest security patches
  • info: Informational findings, no direct security impact
  • low: Minor security issues with limited impact
  • medium: Moderate vulnerabilities requiring attention
  • high: Serious vulnerabilities with significant risk
  • critical: Severe vulnerabilities requiring immediate action

Template variables

Nuclei provides built-in variables for dynamic values:

Global variables

{{BaseURL}}
string
Complete base URL including protocol (e.g., https://example.com)
{{Hostname}}
string
Hostname or IP address (e.g., example.com)
{{Host}}
string
Hostname with port if non-standard (e.g., example.com:8080)
{{Port}}
string
Port number (e.g., 443)
{{Scheme}}
string
URL scheme (e.g., https)
{{RootURL}}
string
Root URL without path (e.g., https://example.com)
{{FQDN}}
string
Fully qualified domain name (for DNS templates)

Usage example

http:
  - method: GET
    path:
      - "{{BaseURL}}/admin/"
      - "{{BaseURL}}/api/v1/users"
    
    headers:
      Host: "{{Hostname}}"
      Origin: "{{RootURL}}"

Comments

Use # for comments:
# This is a comment
id: example-template

info:
  name: Example  # Inline comment
  author: pdteam
  # This section checks for exposed files
  severity: medium

Special characters

Escaping

When strings contain special YAML characters, use quotes:
# Quotes required
regex:
  - "<title>([^<]+)</title>"  # Contains < >
  - "{{BaseURL}}"              # Contains {{ }}
  - "key: value"               # Contains :

# No quotes needed
regex:
  - "[0-9]+"
  - "simple-pattern"

Multi-line strings

Preserves line breaks:
raw:
  - |
    GET /api HTTP/1.1
    Host: {{Hostname}}
    User-Agent: Scanner

Naming conventions

Template IDs

Good IDs: git-config-exposure, apache-log4j-rce, wordpress-plugin-sqliBad IDs: Template1, my_template, CHECK-EVERYTHING
Rules for template IDs:
  • Use lowercase letters
  • Separate words with hyphens
  • Be descriptive but concise
  • Include CVE ID if applicable: CVE-2021-1234
  • Use technology name: apache-, nginx-, wordpress-

Field names

Nuclei uses kebab-case for field names:
# Correct
stop-at-first-match: true
max-redirects: 5
cookie-reuse: true

# Incorrect (these won't work)
stopAtFirstMatch: true
max_redirects: 5
CookieReuse: true

Validation

Validate your template syntax before use:
# Validate single template
nuclei -validate -t template.yaml

# Validate all templates in directory
nuclei -validate -t ./templates/

# Show detailed errors
nuclei -validate -t template.yaml -v
The validator checks:
  • YAML syntax correctness
  • Required fields presence
  • Field type matching
  • Matcher and extractor logic
  • Protocol-specific requirements

Common syntax errors

# Wrong - inconsistent indentation
http:
  - method: GET
   path:  # Mixed spaces
     - "{{BaseURL}}"

# Correct
http:
  - method: GET
    path:
      - "{{BaseURL}}"
# Wrong - special characters need quotes
regex:
  - {{BaseURL}}/path

# Correct
regex:
  - "{{BaseURL}}/path"
# Wrong - mixing formats
words:
  - word1
  word2

# Correct
words:
  - word1
  - word2

Editor support

VS Code

  • YAML extension by Red Hat
  • Nuclei Template Snippets extension
  • Configure tab-to-spaces conversion

JetBrains IDEs

  • Built-in YAML support
  • File > Settings > Editor > Code Style > YAML
  • Set indent to 2 spaces

Next steps

Write your first template

Follow step-by-step guide to create a working template

Template structure

Deep dive into template components

Build docs developers (and LLMs) love