Nuclei Vulnerability Scanner: Fast Template-Based Security Testing
How to install Nuclei, run vulnerability templates, write custom templates, and integrate the scanner into CI/CD pipelines for automated security testing.
Nuclei Vulnerability Scanner: Fast Template-Based Security Testing
Nuclei, built by ProjectDiscovery, is a fast, configurable vulnerability scanner that executes security checks using YAML templates. Unlike traditional scanners that embed logic in compiled code, Nuclei separates the scanning engine from the detection logic — making it trivially easy to add new checks, share them with the community, and customize detection for your specific targets. The template library contains over 9,000 community-contributed checks covering CVEs, misconfigurations, exposed panels, default credentials, and more. This guide covers installation, running templates, writing custom templates, and CI integration.
Installation
Go install (recommended):
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
Homebrew:
brew install nuclei
Docker:
docker pull projectdiscovery/nuclei:latest
Update templates after installation:
nuclei -update-templates
Templates are stored in ~/nuclei-templates/. Nuclei automatically updates them when running, but nuclei -update-templates forces an immediate refresh.
Basic Scanning
Scan a single target with all templates:
nuclei -u https://example.com
Scan a list of targets:
nuclei -list targets.txt
Filter by severity:
nuclei -u https://example.com -severity critical,high,medium
Filter by template tags:
nuclei -u https://example.com -tags cve,oast
nuclei -u https://example.com -tags misconfig,exposure
nuclei -u https://example.com -tags apache,nginx,iis
Run a specific template or directory:
nuclei -u https://example.com -t cves/2023/CVE-2023-44487.yaml
nuclei -u https://example.com -t cves/2023/
nuclei -u https://example.com -t ~/nuclei-templates/exposures/
Output formats:
nuclei -u https://example.com -o results.txt
nuclei -u https://example.com -json -o results.json
nuclei -u https://example.com -sarif-export results.sarif
Concurrency control. Nuclei runs many templates in parallel by default. Tune for aggressive scanning or to reduce server load:
# Reduce load on target
nuclei -u https://staging.example.com -c 5 -rate-limit 10
# Faster scanning (higher resource use)
nuclei -u https://staging.example.com -c 50 -rate-limit 500
Understanding Template Categories
The template library is organized by category:
cves/— Checks for specific CVEs by year and ID. Regularly updated as new CVEs are published.exposures/— Detects exposed files, configs, and admin panels (.envfiles, Git repos, backup files, phpMyAdmin).misconfigurations/— Common server and application misconfigs (open redirects, CORS wildcards, debug endpoints).default-logins/— Tests default credentials against management interfaces (Jenkins, GitLab, Grafana, routers).technologies/— Technology fingerprinting (identify the stack before targeted testing).network/— TCP/UDP service checks (open databases, Redis without auth, exposed Memcached).dns/— DNS misconfigurations and subdomain takeover checks.ssl/— TLS configuration issues (expired certs, weak ciphers, BEAST/POODLE).
A practical recon + vulnerability workflow:
# First, fingerprint the technology stack
nuclei -u https://example.com -tags tech -silent
# Then run relevant CVEs and misconfigs
nuclei -u https://example.com -tags cve,misconfig -severity critical,high
Writing Custom Templates
Custom templates let you encode application-specific checks that the community library does not cover.
Template structure:
id: template-id
info:
name: "Descriptive name for the check"
author: "your-handle"
severity: medium
description: "What this template detects and why it matters"
tags: custom,exposure
http:
- method: GET
path:
- "{{BaseURL}}/admin/config"
- "{{BaseURL}}/api/v1/internal/config"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
words:
- "database_password"
- "db_secret"
condition: or
part: body
Example: Detect exposed Spring Boot Actuator endpoints:
id: spring-boot-actuator-exposed
info:
name: "Spring Boot Actuator Endpoints Exposed"
author: "security-team"
severity: high
description: >
Spring Boot Actuator endpoints are publicly accessible, potentially
exposing application internals, environment variables, and heap dumps.
tags: springboot,exposure,misconfig
http:
- method: GET
path:
- "{{BaseURL}}/actuator"
- "{{BaseURL}}/actuator/env"
- "{{BaseURL}}/actuator/heapdump"
stop-at-first-match: true
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
words:
- "_links"
- "activeProfiles"
part: body
condition: or
Example: Check for a specific API endpoint returning internal data:
id: internal-user-data-leak
info:
name: "Internal User Data Exposed in API Response"
severity: critical
tags: custom,api,exposure
http:
- method: GET
path:
- "{{BaseURL}}/api/users?include=internal"
headers:
Accept: "application/json"
matchers-condition: and
matchers:
- type: status
status:
- 200
- type: word
words:
- "password_hash"
- "ssn"
- "credit_card"
part: body
condition: or
extractors:
- type: regex
name: leaked-field
regex:
- '"(password_hash|ssn|credit_card)"\s*:'
part: body
Testing templates before deployment:
nuclei -u https://staging.example.com -t custom-templates/ -debug
The -debug flag shows full request/response pairs, making it easy to understand why a template matches or does not match.
Out-of-Band (OOB) Testing with OAST
Nuclei integrates with interactsh for out-of-band detection — essential for blind vulnerabilities like Log4Shell, SSRF, and blind XSS where the payload effect is not reflected in the HTTP response.
# Use ProjectDiscovery's hosted interactsh
nuclei -u https://example.com -tags oast -interactsh-url https://oast.live
# Run your own interactsh server
interactsh-server -domain your-oob-domain.com
nuclei -u https://example.com -tags oast -interactsh-url https://your-oob-domain.com
Templates using {{interactsh-url}} inject an OOB callback URL. When the target makes a DNS or HTTP request to that URL (indicating the payload fired), Nuclei records the match.
CI/CD Integration
GitHub Actions
name: Nuclei Vulnerability Scan
on:
schedule:
- cron: '0 6 * * *' # Daily at 6am UTC
workflow_dispatch: {}
jobs:
nuclei-scan:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Nuclei
uses: projectdiscovery/nuclei-action@main
with:
target: https://staging.example.com
flags: >
-severity critical,high
-tags cve,misconfig,exposure
-exclude-tags dos
-rate-limit 20
-sarif-export nuclei-results.sarif
github-report: true
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Upload SARIF results
uses: github/codeql-action/upload-sarif@v3
if: always()
with:
sarif_file: nuclei-results.sarif
The github-report: true option creates a GitHub issue with the scan report automatically.
Blocking PRs on New Critical Findings
For a security gate that fails PRs when new critical vulnerabilities are detected:
- name: Nuclei gate
run: |
nuclei \
-u https://staging.example.com \
-severity critical \
-tags cve \
-exclude-tags dos \
-json \
-o nuclei-output.json
CRIT_COUNT=$(cat nuclei-output.json | jq '. | length' 2>/dev/null || echo 0)
echo "Critical findings: $CRIT_COUNT"
if [ "$CRIT_COUNT" -gt "0" ]; then
echo "Build failed: critical vulnerabilities detected"
cat nuclei-output.json | jq -r '.info.name + " — " + .host'
exit 1
fi
Safe Scanning Practices
Always exclude DoS templates. The -exclude-tags dos flag prevents templates that can crash or degrade the target service. Never run DoS templates against production.
Use -interactsh-disable in offline or air-gapped environments to prevent OOB callbacks that could leak target information.
Rate limit responsibly. Use -rate-limit 10 when scanning production-adjacent environments to avoid triggering WAF rules or alert fatigue in your monitoring.
Scope your scans. Use -include-hosts and -exclude-hosts to constrain scanning to in-scope assets:
nuclei -list all-hosts.txt \
-exclude-hosts out-of-scope.txt \
-severity critical,high \
-exclude-tags dos,fuzz
Maintaining a Custom Template Repository
For teams with internal applications, maintain a private template repository:
# Add custom templates directory
nuclei -u https://example.com \
-t ~/nuclei-templates/ \
-t ~/company-templates/
# Or set in config
# ~/.config/nuclei/config.yaml
template-path:
- ~/nuclei-templates
- ~/company-templates
Store custom templates in version control, require peer review for new templates (especially those with severity: critical), and run automated template tests with nuclei -validate -t company-templates/ to catch YAML syntax errors before deployment.