Skip to main content
COSMICBYTEZLABS
NewsSecurityHOWTOsToolsTraining
StudyProjectsNewsletterHire MeAbout
Subscribe

Press Enter to search or Esc to close

News
Security
HOWTOs
Tools
Training
Study
Projects
Newsletter
Hire Me
About
RSS Feed
Reading List
Subscribe

Stay in the Loop

Get the latest security alerts, tutorials, and tech insights delivered to your inbox.

Subscribe NowFree forever. No spam.
COSMICBYTEZLABS

Your trusted source for IT intelligence, cybersecurity insights, and hands-on technical guides.

1913+ Articles
150+ Guides

CONTENT

  • Latest News
  • Security Alerts
  • HOWTOs
  • Checklists
  • Projects
  • Exam Prep

RESOURCES

  • Search
  • Browse Tags
  • Newsletter Archive
  • Reading List
  • RSS Feed

COMPANY

  • About Us
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CosmicBytez Labs. All rights reserved.

System Status: Operational
  1. Home
  2. Projects
  3. Nuclei Vulnerability Scanning Pipeline
Nuclei Vulnerability Scanning Pipeline
PROJECTIntermediate

Nuclei Vulnerability Scanning Pipeline

Build an automated vulnerability scanning pipeline using ProjectDiscovery's Nuclei and companion tools — subfinder, httpx, and naabu — to continuously probe authorized targets for CVEs, misconfigurations, and exposures.

Dylan H.

Projects

July 15, 2026
11 min read
3-5 hours

Tools & Technologies

Nuclei v3subfinderhttpxnaabudnsxDockerDVWAOWASP Juice Shop

Overview

Nuclei is a fast, template-driven vulnerability scanner from ProjectDiscovery. Unlike traditional scanners that rely on static signatures, Nuclei uses a community-maintained library of YAML templates — over 9,000 at the time of writing — to detect CVEs, misconfigurations, exposed files, default credentials, subdomain takeovers, and more.

In this project you will wire together the full ProjectDiscovery open-source toolkit into an end-to-end scanning pipeline:

  1. subfinder — passive subdomain enumeration
  2. dnsx — DNS resolution and filtering
  3. naabu — fast port scanning
  4. httpx — HTTP service probing and technology fingerprinting
  5. Nuclei — template-based vulnerability detection and reporting

The result is a repeatable, scriptable pipeline you can run against your own infrastructure or authorized bug-bounty targets. All testing in this guide is performed against intentionally vulnerable local Docker containers — never against systems you do not own or have explicit written permission to test.


Architecture

┌──────────────────────────────────────────────────────────────┐
│                   Scanning Pipeline                          │
│                                                              │
│  subfinder → dnsx → naabu → httpx → Nuclei → Results        │
│                                                              │
│  ┌─────────┐   ┌──────┐   ┌───────┐   ┌───────┐            │
│  │Subdomains│→ │Resolved│→ │Open   │→  │Live   │            │
│  │(passive) │  │IPs   │  │Ports  │   │Hosts  │            │
│  └─────────┘   └──────┘   └───────┘   └───────┘            │
│                                            │                 │
│                                        ┌───▼────────────┐   │
│                                        │ Nuclei Engine  │   │
│                                        │ 9000+ templates│   │
│                                        └───┬────────────┘   │
│                                            │                 │
│                              ┌─────────────▼─────────┐      │
│                              │ JSONL / SARIF / Text  │      │
│                              │ Output & Integrations │      │
│                              └───────────────────────┘      │
└──────────────────────────────────────────────────────────────┘

Each stage feeds directly into the next via stdin/stdout pipes, making the whole pipeline composable and easy to extend. You can swap any tool or skip stages depending on your scope.


Prerequisites

  • Linux or macOS system (Ubuntu 22.04+ recommended)
  • Go 1.21 or newer
  • Docker and Docker Compose (for the local lab targets)
  • 4 GB RAM minimum; 8 GB recommended for larger scans

Verify your Go version:

go version
# go version go1.24.x linux/amd64

If you don't have Go installed:

# Ubuntu / Debian
sudo apt update && sudo apt install -y golang-go
 
# macOS
brew install go
 
# Verify
go version

Step 1 — Install the ProjectDiscovery Toolkit

Install all five tools with go install. Each binary lands in ~/go/bin/, which should be on your PATH.

# Add ~/go/bin to PATH if not already there
echo 'export PATH="$HOME/go/bin:$PATH"' >> ~/.bashrc
source ~/.bashrc
 
# Install the toolkit
go install -v github.com/projectdiscovery/subfinder/v2/cmd/subfinder@latest
go install -v github.com/projectdiscovery/dnsx/cmd/dnsx@latest
go install -v github.com/projectdiscovery/naabu/v2/cmd/naabu@latest
go install -v github.com/projectdiscovery/httpx/cmd/httpx@latest
go install -v github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest

Verify everything installed correctly:

nuclei   -version
subfinder -version
httpx    -version
naabu    -version
dnsx     -version

Update Nuclei Templates

Nuclei ships without templates. Pull the full community template library:

nuclei -update-templates
# Templates saved to: ~/.nuclei-templates/

Check the template count:

find ~/.nuclei-templates -name "*.yaml" | wc -l
# Should be 9000+

Re-run nuclei -update-templates periodically — the community adds dozens of new templates every week.


Step 2 — Stand Up Local Lab Targets

Before scanning anything on the internet, practise against intentionally vulnerable applications running locally. Two excellent Docker images cover the most common vulnerability classes.

# Create a dedicated Docker network for the lab
docker network create vuln-lab
 
# DVWA — Damn Vulnerable Web Application (PHP/MySQL)
docker run -d \
  --name dvwa \
  --network vuln-lab \
  -p 8080:80 \
  vulnerables/web-dvwa
 
# OWASP Juice Shop — modern Node.js vulnerable app
docker run -d \
  --name juiceshop \
  --network vuln-lab \
  -p 3000:3000 \
  bkimminich/juice-shop

Wait about 30 seconds for both containers to initialise, then confirm they're reachable:

curl -s -o /dev/null -w "%{http_code}" http://localhost:8080
# 200
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000
# 200

Open DVWA at http://localhost:8080 in your browser and log in with admin / password. Set the security level to Low under DVWA Security to expose the widest attack surface for testing.


Step 3 — Your First Nuclei Scan

Run a basic scan against both targets and watch the output:

# Scan DVWA
nuclei -u http://localhost:8080 -v
 
# Scan Juice Shop
nuclei -u http://localhost:3000 -v

The -v flag shows each template being tried in real time. You should see findings within seconds — exposed panels, default credentials, misconfigured headers, and known CVEs in bundled libraries.

Narrow the Scope

For day-to-day use you rarely want to run all 9,000+ templates. Filter by severity or tag:

# Only high and critical findings
nuclei -u http://localhost:8080 -severity high,critical
 
# Only misconfiguration templates
nuclei -u http://localhost:8080 -tags misconfig
 
# Only CVE templates
nuclei -u http://localhost:8080 -tags cves
 
# Exposed files and sensitive data
nuclei -u http://localhost:8080 -tags exposures
 
# Default credentials
nuclei -u http://localhost:8080 -tags default-logins

Step 4 — Save and Parse Results

Plain-text output is fine for exploration, but for any systematic workflow you want structured output.

JSONL (JSON Lines)

Each finding is one JSON object per line — easy to parse with jq or ingest into Elasticsearch, Splunk, or a SIEM:

nuclei -u http://localhost:8080 \
  -tags cves,misconfig,exposures \
  -jsonl \
  -o results.jsonl
 
# Pretty-print a single finding
head -1 results.jsonl | jq .
 
# Count by severity
jq -r '.info.severity' results.jsonl | sort | uniq -c | sort -rn
 
# Extract unique template IDs
jq -r '.["template-id"]' results.jsonl | sort -u

SARIF (for CI/CD)

SARIF is the standard format for security tooling in GitHub Actions, GitLab CI, and Azure DevOps:

nuclei -u http://localhost:8080 \
  -tags cves,misconfig \
  -sarif-export results.sarif

Upload results.sarif as a GitHub Code Scanning artifact to get findings annotated directly on pull requests.


Step 5 — Build the Full Pipeline

Now chain all the tools together. Create a project directory and a reusable scan script:

mkdir -p ~/nuclei-lab && cd ~/nuclei-lab

Create pipeline.sh:

#!/usr/bin/env bash
# pipeline.sh — Full ProjectDiscovery scanning pipeline
# Usage: ./pipeline.sh <domain>
# WARNING: Only use against systems you own or have written permission to test.
 
set -euo pipefail
 
TARGET="${1:?Usage: $0 <domain>}"
OUTDIR="results/$(date +%Y%m%d_%H%M%S)_${TARGET}"
mkdir -p "$OUTDIR"
 
echo "[*] Target: $TARGET"
echo "[*] Output: $OUTDIR"
echo ""
 
# ── Stage 1: Passive subdomain discovery ──────────────────────
echo "[+] Stage 1/5 — Subdomain discovery"
subfinder -d "$TARGET" \
  -o "$OUTDIR/subdomains.txt" \
  -silent
SUBCOUNT=$(wc -l < "$OUTDIR/subdomains.txt")
echo "    Found $SUBCOUNT subdomains"
 
# ── Stage 2: DNS resolution ────────────────────────────────────
echo "[+] Stage 2/5 — DNS resolution"
dnsx -l "$OUTDIR/subdomains.txt" \
  -o "$OUTDIR/resolved.txt" \
  -silent
RESCOUNT=$(wc -l < "$OUTDIR/resolved.txt")
echo "    Resolved $RESCOUNT hosts"
 
# ── Stage 3: Port scanning ─────────────────────────────────────
echo "[+] Stage 3/5 — Port scanning (top 1000)"
naabu -l "$OUTDIR/resolved.txt" \
  -top-ports 1000 \
  -o "$OUTDIR/open-ports.txt" \
  -silent
PORTCOUNT=$(wc -l < "$OUTDIR/open-ports.txt")
echo "    Found $PORTCOUNT open host:port combos"
 
# ── Stage 4: HTTP probing ──────────────────────────────────────
echo "[+] Stage 4/5 — HTTP probing"
httpx -l "$OUTDIR/open-ports.txt" \
  -o "$OUTDIR/live-hosts.txt" \
  -status-code \
  -tech-detect \
  -silent
LIVECOUNT=$(wc -l < "$OUTDIR/live-hosts.txt")
echo "    Found $LIVECOUNT live HTTP services"
 
# ── Stage 5: Vulnerability scanning ───────────────────────────
echo "[+] Stage 5/5 — Nuclei scan"
nuclei -l "$OUTDIR/live-hosts.txt" \
  -tags cves,misconfig,exposures,default-logins \
  -severity low,medium,high,critical \
  -rate-limit 150 \
  -concurrency 25 \
  -jsonl \
  -o "$OUTDIR/vulnerabilities.jsonl" \
  -silent
 
VULNCOUNT=$(wc -l < "$OUTDIR/vulnerabilities.jsonl")
echo "    Found $VULNCOUNT findings"
echo ""
 
# ── Summary ────────────────────────────────────────────────────
echo "── Scan Summary ──────────────────────────────"
echo "  Subdomains : $SUBCOUNT"
echo "  Resolved   : $RESCOUNT"
echo "  Open ports : $PORTCOUNT"
echo "  Live HTTP  : $LIVECOUNT"
echo "  Findings   : $VULNCOUNT"
echo "──────────────────────────────────────────────"
echo "  Results in : $OUTDIR/"

Make it executable and run it against your local lab (using localhost as a stand-in for demonstration; for a real domain scan replace accordingly):

chmod +x pipeline.sh
 
# For your local lab targets, scan them directly with Nuclei
# (subfinder/dnsx/naabu don't apply to localhost, so use the one-stage version)
nuclei -l <(echo -e "http://localhost:8080\nhttp://localhost:3000") \
  -tags cves,misconfig,exposures,default-logins \
  -severity low,medium,high,critical \
  -rate-limit 50 \
  -jsonl \
  -o results.jsonl

Quick One-Liner Pipeline

For a fast scan against a real authorized domain:

subfinder -d example.com -silent \
  | httpx -silent \
  | nuclei -tags cves,misconfig -severity high,critical -silent

Step 6 — Write a Custom Template

Understanding the template format lets you write checks for proprietary software or internal services that the community doesn't cover.

Create templates/custom-admin-panel.yaml:

id: custom-admin-panel-exposure
 
info:
  name: Exposed Admin Panel
  author: cosmicbytez
  severity: medium
  description: Detects an exposed administrative panel without authentication.
  tags:
    - misconfig
    - exposure
    - admin
 
http:
  - method: GET
    path:
      - "{{BaseURL}}/admin"
      - "{{BaseURL}}/admin/login"
      - "{{BaseURL}}/wp-admin"
      - "{{BaseURL}}/administrator"
      - "{{BaseURL}}/manage"
 
    matchers-condition: and
    matchers:
      - type: status
        status:
          - 200
 
      - type: word
        words:
          - "admin"
          - "dashboard"
          - "panel"
          - "login"
        condition: or
        case-insensitive: true
 
    extractors:
      - type: regex
        name: title
        regex:
          - "<title>([^<]+)</title>"
        group: 1

Run your custom template:

nuclei -u http://localhost:8080 \
  -t templates/custom-admin-panel.yaml \
  -v

Workflow Templates

Nuclei supports conditional workflows that chain templates together. Create templates/tech-then-cve.yaml:

workflows:
  - template: technologies/wordpress-detect.yaml
    matchers:
      - name: wordpress
        subtemplates:
          - tags: wordpress,cves
 
  - template: technologies/joomla-detect.yaml
    matchers:
      - name: joomla
        subtemplates:
          - tags: joomla,cves

This first detects which CMS is present, then runs only the relevant CVE templates — dramatically reducing noise and scan time.


Step 7 — Tune Performance and Rate Limiting

Untuned Nuclei can flood small targets or trigger WAF blocks. Adjust these flags to match your environment:

nuclei -l targets.txt \
  -rate-limit 50          `# Max requests/second globally` \
  -rate-limit-minute 500  `# Max requests/minute` \
  -concurrency 10         `# Parallel template executions` \
  -timeout 10             `# Per-request timeout in seconds` \
  -retries 1              `# Retry failed requests once` \
  -bulk-size 25           `# URLs processed per template batch`

Persist your preferred defaults in ~/.config/nuclei/config.yaml so you don't have to repeat them:

rate-limit: 100
concurrency: 20
timeout: 10
retries: 1
exclude-tags:
  - dos       # Never run DoS templates automatically
  - fuzz      # Fuzzing templates are noisy; run manually
severity:
  - low
  - medium
  - high
  - critical

Testing

Confirm Findings Against DVWA

Run a targeted scan to confirm your pipeline catches known vulnerabilities in DVWA:

nuclei -u http://localhost:8080 \
  -tags default-logins,misconfig,exposures \
  -v 2>&1 | tee dvwa-scan.txt
 
grep -E "(CRITICAL|HIGH|MEDIUM)" dvwa-scan.txt | head -20

You should see findings for: default admin credentials, missing security headers (HSTS, X-Frame-Options, CSP), exposed phpinfo pages, and SQL injection indicators.

Confirm Findings Against Juice Shop

nuclei -u http://localhost:3000 \
  -tags misconfig,exposures,cves \
  -v 2>&1 | tee juiceshop-scan.txt
 
jq -r '[.["template-id"], .info.severity, .host] | @tsv' results.jsonl \
  | column -t \
  | sort -k2

Juice Shop is based on a known-vulnerable Node.js stack and should produce multiple medium-to-high findings around exposed API endpoints, missing headers, and known npm dependency CVEs.

Validate Custom Templates

# Validate YAML syntax before running
nuclei -validate -t templates/custom-admin-panel.yaml
 
# Dry-run to list what would be scanned
nuclei -u http://localhost:8080 \
  -t templates/custom-admin-panel.yaml \
  -list-templates

Integrations

GitHub Actions — Scan on Every PR

Add vulnerability scanning to your CI/CD pipeline so new code changes are checked automatically. Create .github/workflows/nuclei-scan.yml:

name: Nuclei Vulnerability Scan
 
on:
  pull_request:
    branches: [main]
 
jobs:
  nuclei:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
 
      - name: Install Nuclei
        run: go install github.com/projectdiscovery/nuclei/v3/cmd/nuclei@latest
 
      - name: Update templates
        run: nuclei -update-templates
 
      - name: Run scan against staging
        env:
          STAGING_URL: ${{ secrets.STAGING_URL }}
        run: |
          nuclei -u "$STAGING_URL" \
            -tags cves,misconfig \
            -severity high,critical \
            -sarif-export results.sarif \
            -rate-limit 50
 
      - name: Upload SARIF results
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif

Elasticsearch + Kibana Dashboard

Forward JSONL output to Elasticsearch for long-term tracking and dashboarding:

# Send findings to local Elasticsearch
nuclei -l targets.txt \
  -jsonl \
  -o - \
  | while IFS= read -r line; do
      curl -s -X POST "http://localhost:9200/nuclei-findings/_doc" \
        -H "Content-Type: application/json" \
        -d "$line" > /dev/null
    done

Or use Nuclei's built-in Elasticsearch integration:

nuclei -l targets.txt \
  -es-db http://localhost:9200 \
  -es-index nuclei-findings-$(date +%Y%m)

Build a Kibana dashboard using the info.severity, template-id, and host fields for a live vulnerability heat-map across your infrastructure.


Deployment — Scheduling Regular Scans

Cron Job

Run the pipeline nightly against your own infrastructure:

crontab -e
# Run nuclei against internal lab targets every night at 02:00
0 2 * * * /home/user/nuclei-lab/pipeline.sh yourdomain.internal >> /var/log/nuclei-scans.log 2>&1

Docker-Compose Setup

Run Nuclei as a containerised service alongside Elasticsearch for a persistent scanning appliance:

# docker-compose.yml
services:
  nuclei:
    image: projectdiscovery/nuclei:latest
    volumes:
      - ./targets:/targets
      - ./results:/results
      - nuclei-templates:/root/.nuclei-templates
    command: >
      -l /targets/hosts.txt
      -tags cves,misconfig
      -severity high,critical
      -jsonl
      -o /results/scan-$(date +%Y%m%d).jsonl
      -rate-limit 100
    depends_on:
      - elasticsearch
 
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    environment:
      - discovery.type=single-node
      - xpack.security.enabled=false
    ports:
      - "9200:9200"
    volumes:
      - es-data:/usr/share/elasticsearch/data
 
volumes:
  nuclei-templates:
  es-data:

Extensions and Next Steps

Expand the Template Library

Beyond the default community templates, explore these resources:

  • nuclei-templates — the official community repo
  • fuzzing-templates — parameter fuzzing templates for deeper testing
  • Custom org templates — maintain a private repo of templates specific to your stack and keep them alongside the community set with -t ~/.nuclei-templates -t ~/.my-org-templates

Add Katana for Crawling

Katana discovers URLs that httpx alone misses — forms, JavaScript-rendered endpoints, and API paths — giving Nuclei a richer target list:

go install github.com/projectdiscovery/katana/cmd/katana@latest
 
subfinder -d example.com -silent \
  | httpx -silent \
  | katana -silent \
  | nuclei -tags cves,misconfig -silent

Integrate with PDCP (ProjectDiscovery Cloud Platform)

ProjectDiscovery offers a hosted dashboard for team-level vulnerability management, deduplication, and alerting. Connect your self-hosted scans with:

nuclei -l targets.txt \
  -cloud-upload \
  -auth <your-pdcp-api-key>

Feed Findings into Wazuh or Your SIEM

If you built the Wazuh XDR/SIEM homelab, pipe Nuclei's JSONL output into Wazuh's active-response engine to auto-isolate hosts with critical vulnerabilities, or forward via Filebeat to the central index for correlation with EDR events.

Template Development Workflow

Level up your template skills:

  1. Use the Nuclei Template Editor online playground
  2. Study similar community templates before writing from scratch
  3. Always run nuclei -validate -t your-template.yaml before committing
  4. Submit novel findings back to the community repo via pull request

Key Takeaways

Nuclei transforms ad-hoc vulnerability testing into a repeatable, auditable pipeline. The core strengths are:

  • Speed — thousands of templates run concurrently with minimal overhead
  • Breadth — CVEs, misconfigs, exposures, default credentials, and takeovers in one tool
  • Composability — stdin/stdout pipes connect every stage; swap tools as needed
  • Community — templates are updated constantly as new CVEs drop
  • Flexibility — YAML templates are readable, writable, and versionable in git

Start by scanning your own homelab, graduate to authorized bug-bounty targets, and use the SARIF integration to bake vulnerability scanning into your CI/CD pipeline so regressions never ship to production.

#vulnerability-scanning#projectdiscovery#nuclei#recon#automation#offensive-security

Related Articles

Claude Code for IT Operations: Building a Multi-Project

Transform Claude Code from a chatbot into a DevOps co-pilot. Set up CLAUDE.md templates, custom hooks, reusable agents, deployment skills, and MCP server...

12 min read

Securing AI-Assisted Development with Claude Code

Build guardrails around AI-generated code with Claude Code hooks, security-scanning agents, OWASP-aware prompting, and automated secret detection. A...

13 min read

CI/CD Pipeline with GitHub Actions and Azure

Build a secure CI/CD pipeline with GitHub Actions deploying to Azure. Covers build, test, security scanning (SAST/DAST), and deployment with OIDC...

11 min read
Back to all Projects