# Nuclei False Positive Handling Guide ## Table of Contents - [Understanding False Positives](#understanding-false-positives) - [Common False Positive Scenarios](#common-false-positive-scenarios) - [Verification Techniques](#verification-techniques) - [Template Filtering Strategies](#template-filtering-strategies) - [Custom Template Refinement](#custom-template-refinement) ## Understanding False Positives False positives occur when Nuclei reports a finding that doesn't represent an actual security vulnerability in the context of your application. ### Types of False Positives 1. **Context-Specific**: Finding is valid in general but not applicable to your application 2. **Version-Specific**: CVE template triggers but your version is patched 3. **Configuration-Based**: Security control exists but Nuclei can't detect it 4. **Pattern Matching Errors**: Regex/word matchers trigger on benign content ## Common False Positive Scenarios ### 1. Missing Security Headers (Info/Low Severity) **Finding**: Missing `X-Frame-Options`, `Content-Security-Policy` **False Positive When**: - Headers set at CDN/WAF level (not visible to scanner) - Application is not intended for browser rendering (pure API) - Modern browsers already protect against clickjacking **Verification**: ```bash # Check headers from actual browser curl -I https://target-app.com curl -I https://target-app.com -H "User-Agent: Mozilla/5.0" # Check if CDN adds headers curl -I https://target-app.com -v 2>&1 | grep -i "x-frame-options\|content-security" ``` **Filter Strategy**: ```bash # Exclude header-related info findings nuclei -u https://target-app.com -etags headers -severity critical,high ``` ### 2. Directory Listing / Exposed Paths **Finding**: Directory listing enabled, exposed paths like `/admin`, `/backup` **False Positive When**: - Path requires authentication (Nuclei tested unauthenticated) - Path is intentionally public (documentation, public assets) - CDN/WAF blocks access (returns 200 with error page) **Verification**: ```bash # Manual verification with authentication curl https://target-app.com/admin \ -H "Authorization: Bearer $TOKEN" \ -H "Cookie: session=$SESSION" # Check actual response content curl https://target-app.com/backup | head -20 ``` **Filter Strategy**: ```bash # Exclude exposure templates for authenticated scans nuclei -u https://target-app.com \ -header "Authorization: Bearer $TOKEN" \ -etags exposure ``` ### 3. CVE Templates Against Patched Versions **Finding**: CVE-2024-XXXXX detected **False Positive When**: - Application version is patched but template matches on generic patterns - Backported patches applied without version number change - Template uses loose detection criteria **Verification**: ```bash # Check actual version curl https://target-app.com/version curl https://target-app.com -v 2>&1 | grep -i "server:" # Cross-reference with CVE details # Check if version is vulnerable per NVD/vendor advisory ``` **Filter Strategy**: ```bash # Scan only recent CVEs nuclei -u https://target-app.com \ -tags cve \ -template-condition "contains(id, 'CVE-2024') || contains(id, 'CVE-2023')" # Exclude specific false positive templates nuclei -u https://target-app.com \ -exclude-id CVE-2018-12345,CVE-2019-67890 ``` ### 4. Technology Detection False Positives **Finding**: WordPress, Drupal, or other CMS detected **False Positive When**: - Generic strings match (like "wp-" in custom code) - Legacy migration artifacts remain - Application mimics CMS structure but isn't actually that CMS **Verification**: ```bash # Check for actual CMS files curl https://target-app.com/wp-admin/ curl https://target-app.com/wp-includes/ curl https://target-app.com/readme.html # Technology fingerprinting whatweb https://target-app.com wappalyzer https://target-app.com ``` **Filter Strategy**: ```bash # Exclude tech detection templates nuclei -u https://target-app.com -etags tech ``` ### 5. Default Login Pages **Finding**: Admin panel or login page detected **False Positive When**: - Panel is legitimate and intended to be accessible - Panel requires MFA even if default credentials work - Detection based on title/strings only without credential testing **Verification**: ```bash # Test if default credentials actually work curl -X POST https://target-app.com/login \ -d "username=admin&password=admin" \ -v # Check if MFA is required curl -X POST https://target-app.com/login \ -d "username=admin&password=admin" \ -c cookies.txt curl https://target-app.com/dashboard \ -b cookies.txt ``` **Filter Strategy**: ```bash # Scan with authentication to skip login detection nuclei -u https://target-app.com \ -header "Authorization: Bearer $TOKEN" \ -etags default-logins,exposed-panels ``` ### 6. API Endpoints Reporting Errors **Finding**: SQL errors, stack traces, or verbose errors detected **False Positive When**: - Errors are intentional validation messages - Stack traces only shown in dev/staging (not production) - API returns structured error JSON (not actual stack trace) **Verification**: ```bash # Check actual error response curl https://api.target.com/endpoint?id=invalid -v # Verify it's not SQL error but validation error curl https://api.target.com/endpoint?id=' OR '1'='1 -v ``` ### 7. CORS Misconfiguration **Finding**: `Access-Control-Allow-Origin: *` **False Positive When**: - Intentional for public APIs - Only applies to non-sensitive endpoints - Additional CORS headers restrict actual access **Verification**: ```bash # Check if sensitive endpoints have CORS curl https://api.target.com/public/data \ -H "Origin: https://evil.com" -v curl https://api.target.com/private/users \ -H "Origin: https://evil.com" \ -H "Authorization: Bearer $TOKEN" -v ``` ## Verification Techniques ### Manual Verification Checklist For each critical/high severity finding: 1. **Reproduce the finding**: ```bash # Use exact URL and parameters from Nuclei output curl "https://target-app.com/vulnerable-path" -v ``` 2. **Check authentication context**: ```bash # Test with authentication curl "https://target-app.com/vulnerable-path" \ -H "Authorization: Bearer $TOKEN" -v ``` 3. **Verify exploitability**: - Can you actually exploit the vulnerability? - Is there a working PoC? - What's the actual impact? 4. **Check mitigating controls**: - WAF rules blocking exploitation - Network segmentation limiting access - Monitoring and alerting in place 5. **Consult security team**: - Discuss edge cases with security engineers - Review against threat model ### Automated Verification Script Use bundled script to batch verify findings: ```bash python3 scripts/verify_findings.py \ --input nuclei-results.jsonl \ --auth-token $AUTH_TOKEN \ --output verified-findings.jsonl ``` ## Template Filtering Strategies ### Strategy 1: Severity-Based Filtering Focus on high-impact findings: ```bash # Critical and high only nuclei -u https://target-app.com -severity critical,high # Exclude info findings nuclei -u https://target-app.com -exclude-severity info ``` ### Strategy 2: Tag-Based Filtering Filter by vulnerability type: ```bash # Only CVEs and OWASP vulnerabilities nuclei -u https://target-app.com -tags cve,owasp # Exclude informational tags nuclei -u https://target-app.com -etags tech,info,headers ``` ### Strategy 3: Template Exclusion Exclude known false positive templates: ```bash # Exclude specific templates nuclei -u https://target-app.com \ -exclude-id CVE-2018-12345,generic-login-panel # Exclude template directories nuclei -u https://target-app.com \ -exclude-templates nuclei-templates/http/misconfiguration/ ``` ### Strategy 4: Custom Template Allowlist Use only verified templates: ```bash # Scan with curated template set nuclei -u https://target-app.com \ -t custom-templates/verified/ \ -t nuclei-templates/http/cves/2024/ ``` ### Strategy 5: Conditional Template Execution Use template conditions: ```bash # Only recent critical CVEs nuclei -u https://target-app.com \ -tags cve \ -severity critical \ -template-condition "contains(id, 'CVE-2024')" ``` ## Custom Template Refinement ### Improving Matcher Accuracy **Before (High False Positives)**: ```yaml matchers: - type: word words: - "admin" ``` **After (Lower False Positives)**: ```yaml matchers-condition: and matchers: - type: status status: - 200 - type: word part: body words: - "admin" - "dashboard" - "login" condition: and - type: regex regex: - '