A Python-based defensive security tool that combines TCP port scanning with CVE cross-referencing, and basic OWASP-style web application checks, into a single CLI with professional CLI + HTML reporting.
Built as a cybersecurity portfolio project to demonstrate practical skills in vulnerability assessment, CVE research, and OWASP Top 10 fundamentals.
This tool is for educational purposes and authorized security testing only.
- Only run this tool against systems you own, or for which you have explicit, documented, written permission to test.
- Unauthorized scanning of networks or web applications you do not own or control may violate laws such as the Computer Fraud and Abuse Act (US), the Computer Misuse Act (UK), the EU Cybercrime Directive, or equivalent legislation in your country, and can carry serious civil and criminal penalties.
- This tool performs detection and enumeration only. It contains no exploitation modules, no destructive payloads, and no data exfiltration logic. SQL injection and XSS checks use single, harmless, non-destructive probes solely to observe error messages or reflected output — they never modify data or execute code.
- The author(s) accept no responsibility or liability for misuse of this tool. You are solely responsible for ensuring you have authorization before scanning any target.
The CLI will always print this disclaimer at startup and requires an
explicit y confirmation (or --yes for scripted/CI use) before scanning.
- Multi-threaded TCP connect scanning via Python's built-in
socketlibrary. - Configurable port ranges/lists (
--ports 1-1024,--ports 22,80,443, etc.). - Banner grabbing for common services (SSH, FTP, HTTP/S, MySQL, etc.) with
lightweight, harmless probes (e.g.
HEAD / HTTP/1.0) for silent services. - Best-effort service/version parsing from banners and
Server:headers. - Optional
--use-nmapmode: ifpython-nmapand thenmapbinary are installed, uses-sVservice/version detection for higher accuracy, gracefully falling back to the socket scanner if unavailable.
- Matches detected
service + versionpairs against a local, offline sample dataset (data/sample_cves.json) simulating NVD-style records — no internet connection needed by default. - Optional
--live-nvdflag queries the real, free NVD REST API 2.0 for additional/live matches, with rate-limit handling and graceful fallback to local-only results on failure. - Each match includes CVE ID, CVSS score, severity (Critical/High/Medium/Low), and a plain-English description.
All checks are passive or single-probe, non-destructive:
- Missing security headers:
Content-Security-Policy,X-Frame-Options,Strict-Transport-Security,X-Content-Type-Options. - Server version disclosure: flags
Server/X-Powered-Byheaders that leak specific version numbers. - SQL injection indicators: appends a single
'to each query parameter and checks the response for known SQL error signatures (MySQL, MSSQL, PostgreSQL, Oracle, SQLite). No UNION/boolean/time-based/destructive payloads are ever sent. - Reflected XSS indicators: injects a harmless, unique marker string into each query parameter and checks whether it is reflected back unescaped. No script ever executes; this only tests output encoding.
- Directory/file enumeration: checks a small wordlist
(
wordlist.txt:robots.txt,.env,.git/config,admin/,backup.zip, etc.) for HTTP 200/401/403 responses — status codes only, no content is downloaded, parsed, or exploited.
- CLI summary: rendered with
rich(colored tables/panels) if installed, falling back totabulate, and finally to plain text — the tool always produces readable output regardless of optional dependencies. - HTML report: a single self-contained
.htmlfile (inline CSS, no external assets) including target info, scan timestamp, open ports/services, matched CVEs with severity, missing security headers, and every finding with a plain-English description and suggested remediation.
vulnerability-scanner/
├── scanner.py # Main CLI entry point
├── port_scanner.py # Network/port scanning logic
├── web_scanner.py # Web app OWASP-style checks
├── cve_lookup.py # CVE matching (local + optional live NVD)
├── report_generator.py # CLI + HTML report generation
├── data/
│ └── sample_cves.json # Sample/simulated CVE dataset
├── wordlist.txt # Common sensitive paths for enumeration
├── requirements.txt
└── README.md
git clone <this-repo>
cd vulnerability-scanner
python3 -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtrich, tabulate, and python-nmap are all optional — the tool degrades
gracefully if any are missing. Only requests is required (for the web
scanner). If you want --use-nmap, you also need the nmap binary
installed on your system (sudo apt install nmap, brew install nmap, etc.).
# Full scan: ports 1-1024 on a host, plus a web scan of its HTTPS site
python scanner.py --target example.com --ports 1-1024 --web \
--url https://example.com --output report.html
# Port scan only, custom range, skip the interactive confirmation prompt
python scanner.py --target 192.168.1.10 --ports 1-65535 --yes
# Web scan only (no --target needed if --url is provided)
python scanner.py --web --url "https://example.com/search?q=test" --output web_report.html
# Include live NVD API lookups alongside the local CVE dataset
python scanner.py --target example.com --ports 1-1024 --live-nvd --nvd-api-key YOUR_KEY
# Use nmap for higher-accuracy service/version detection (requires nmap installed)
python scanner.py --target example.com --ports 1-1024 --use-nmap| Flag | Description | Default |
|---|---|---|
--target |
IP/hostname for the port scan | — |
--ports |
Port range/list, e.g. 1-1024 or 22,80,443 |
1-1024 |
--timeout |
Per-port connection timeout (seconds) | 1.0 |
--threads |
Max concurrent scan threads | 100 |
--use-nmap |
Use python-nmap + nmap binary if available | off |
--web |
Enable the web application scan | off |
--url |
Target URL for the web scan | https://<target> |
--wordlist |
Custom wordlist file path | wordlist.txt |
--live-nvd |
Also query the live NVD API for CVEs | off |
--nvd-api-key |
Optional NVD API key (higher rate limits) | none |
--output |
HTML report output path | report.html |
--yes |
Skip interactive authorization prompt | off |
================================================================================
NETWORK & WEB VULNERABILITY SCANNER - EDUCATIONAL / DEFENSIVE USE ONLY
================================================================================
This tool must ONLY be run against systems you own or have explicit
written permission to test. Unauthorized scanning may be illegal.
By continuing, you confirm you are authorized to scan the specified target.
================================================================================
Do you own this target or have explicit written permission to test it? [y/N]: y
[*] Resolving and scanning 192.168.56.10 (1024 ports, timeout=1.0s, threads=100)...
[*] Target resolved to 192.168.56.10. Found 3 open port(s).
┌───────────────── Vulnerability Scan Report ─────────────────┐
│ Target: 192.168.56.10 │
│ Scan time: 2026-07-11 14:32:05 │
└───────────────────────────────────────────────────────────────┘
Open Ports & Services
┏━━━━━━┳━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Port ┃ Service ┃ Version ┃ Matched CVEs ┃
┡━━━━━━╇━━━━━━━━━╇━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━┩
│ 21 │ vsftpd │ 2.3.4 │ CVE-2011-2523 │
│ 22 │ OpenSSH │ 7.2p2 │ CVE-2016-6210, ... │
│ 80 │ Apache │ 2.4.49 │ CVE-2021-41773, ... │
└──────┴─────────┴──────────┴────────────────────────┘
Total findings: 6
[*] HTML report written to: /home/user/vulnerability-scanner/report.html
The generated report.html presents the same information as a polished,
dark-themed standalone report with color-coded severity badges and
per-finding remediation guidance.
Building this project reinforced several core security-engineering concepts:
- Reconnaissance fundamentals: how TCP connect scans work at the socket level, why banner grabbing sometimes requires an active probe (HTTP) versus a passive read (SSH/FTP), and the tradeoffs of concurrent scanning (thread pool sizing vs. false negatives from short timeouts).
- CVE/vulnerability research workflow: how real tools like Nessus or
OpenVAS map service fingerprints to known CVEs, and the practical
challenges of version-matching (e.g. handling version string ambiguity
like
7.2vs7.2p2). - OWASP Top 10 in practice: implementing safe, indicator-based checks for SQL injection and reflected XSS deepened my understanding of why parameterized queries and output encoding matter — I could directly see how a raw string concatenation leaks a database error, and how missing HTML-encoding turns user input into executable markup.
- Secure-by-default tool design: building in an authorization confirmation gate, avoiding any destructive or exploit code paths, and keeping all payloads harmless-by-construction, so the tool itself can't become a liability even if used carelessly.
- Professional reporting: translating raw technical findings (open ports, missing headers, CVE IDs) into severity-ranked, plain-English findings with actionable remediation — the same structure used in real pentest/vulnerability-assessment reports for clients or stakeholders.
- Graceful degradation: designing the tool so optional dependencies
(
rich,tabulate,python-nmap) enhance the experience but are never required, and so network failures (DNS errors, timeouts, unreachable hosts) produce clear error messages instead of stack traces.
This project pairs naturally with my SafeLine WAF project: where SafeLine sits on the defensive/blocking side of the equation, this scanner represents the assessment side — identifying what a WAF or hardening effort should prioritize.
- CVE matching against the local dataset is sample data for
demonstration — it is not a complete or current mirror of the NVD.
Use
--live-nvdfor real-time data, subject to NVD's public rate limits. - Service/version fingerprinting via raw banners is best-effort and can be fooled by non-standard configurations or banner obfuscation.
- SQL injection and XSS checks are indicators, not proof of exploitability — they are intentionally conservative (single, safe payload) and may produce false negatives on well-defended applications (which is the point: it never attempts to bypass defenses).
- Directory enumeration only checks a small, static wordlist — it is not a
substitute for a full content-discovery tool like
gobusterorffufwhen you have proper authorization to run heavier scans.