A small, modular, non-destructive web security assessment tool. Point it at a domain or IP you own — or are explicitly authorized to test — and it produces a security score, plain-language findings, the attack classes each weakness could enable, evidence, and prioritized remediation. It ships with a FastAPI backend, a zero-dependency dashboard, JSON/HTML/PDF reports, tests, and Docker packaging.
⚠️ Authorized use only. This tool is for assessing systems you own or have written permission to test. It performs assessment and vulnerability intelligence — it never exploits anything. You are responsible for having permission before scanning any target. Unauthorized scanning may violate acceptable-use policies and computer-misuse laws.
- TLS/SSL — certificate issuer/subject/expiry, hostname match, supported protocol versions (TLS 1.0–1.3), negotiated cipher, forward secrecy, plus deeper certificate hygiene: public-key strength (RSA/EC/DSA), signature algorithm (flags SHA-1/MD5), self-signed detection, and over-long validity periods.
- HTTP security headers — HSTS, CSP, X-Content-Type-Options, X-Frame-Options, Referrer-Policy, Permissions-Policy, and the Cross-Origin-* family. Missing headers are explained and risk-rated in context, not treated as automatic exploits.
- Application layer — cookie flags (Secure/HttpOnly/SameSite), CORS policy
(wildcard-with-credentials and origin-reflection), a detailed Content-Security-Policy
review (unsafe-eval, wildcards, missing default-src/object-src/frame-ancestors/base-uri),
HTTP→HTTPS redirect enforcement, mixed content, third-party Subresource Integrity,
and presence of a
security.txtdisclosure policy. - DNS & email security — A/AAAA/MX/NS/TXT/CAA records, SPF (including softfail and multiple-record issues), DMARC, DKIM (common selectors), MTA-STS, and DNSSEC.
- Open ports — an opt-in, rate-limited TCP connect scan over a conservative default port list. Each open port is explained (what the service is and which attack classes target it). No payloads, no auth attempts, no brute force.
- Technology fingerprinting — passive detection from headers, cookies and HTML metadata, each with a confidence score and a plain-language definition.
- Vulnerability intelligence — correlates detected software/versions against public databases (OSV, NVD), classifies each CVE by attack type (RCE, XSS, SQLi, etc.), and flags CISA KEV (known-exploited) entries. No exploit code — only advisory data plus defensive tooling suggestions.
Every deduction is explained: finding, why it matters, severity, the attack classes it could enable, evidence, points deducted, and recommended remediation. Reports open with an executive summary and a prioritized "fix these first" list. The tool never claims a site is "100% secure."
security_scanner/
├── backend/
│ ├── main.py # FastAPI app, mounts API + static frontend
│ ├── config.py # env-driven settings (pydantic-settings)
│ ├── api/routes.py # REST endpoints
│ ├── models/ # Pydantic models (Finding, ScanResult, ...)
│ ├── scanners/ # tls, headers, content, dns, ports, technology, vulnerabilities
│ │ └── knowledge.py # attack glossary, port risks, tech definitions
│ ├── scoring/ # transparent weighted scoring engine
│ ├── services/ # scan orchestration, reports, vuln providers
│ └── utils/ # validation/SSRF guard, safe HTTP client
├── frontend/ # vanilla JS dashboard (index.html, app.js, styles.css)
├── tests/ # unit tests (all external APIs mocked)
├── requirements.txt
├── .env.example
├── Dockerfile
├── docker-compose.yml
└── README.md
Requires Python 3.12+.
Linux / macOS
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # then edit as needed
uvicorn backend.main:app --reloadWindows (PowerShell) — run one line at a time:
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install -r requirements.txt
copy .env.example .env
uvicorn backend.main:app --reloadOpen http://127.0.0.1:8000 — the dashboard is served at the root and the API
lives under /api. Interactive API docs are at /docs.
cp .env.example .env # (Windows: copy .env.example .env)
docker compose up --buildThe app is then available on http://localhost:8000.
| Method | Path | Purpose |
|---|---|---|
| POST | /api/scans |
Start a scan (returns ascan_id) |
| GET | /api/scans/{id} |
Poll status / progress / full result |
| GET | /api/scans/{id}/findings |
Findings only, sorted by severity |
| POST | /api/scans/{id}/cancel |
Cancel a running scan |
| GET | `/api/scans/{id}/report?format=json | html |
| GET | /api/health |
Health check |
| GET | /api/config |
Non-sensitive config for the frontend |
Example:
curl -s -X POST localhost:8000/api/scans \
-H 'content-type: application/json' \
-d '{"target":"https://example.com","authorized":true,"port_scan":false}'Scans run asynchronously; poll GET /api/scans/{id} until status is
completed, failed, or cancelled.
The single choke point is backend/utils/validation.py. Before any network
activity a target is validated and resolved, and by default the tool refuses
anything that resolves to private, loopback, link-local, reserved, or cloud
metadata address space. Protections include:
- SSRF / DNS-rebinding — every redirect hop and every port connection is re-validated against the public-IP rule; resolution is checked at connect time, not just at submission.
- No shell — input is validated for forbidden characters and the tool never
calls
os.system,subprocess(shell=True), or similar. All network work is done withhttpx/asynciosockets. - Bounded work — request timeouts, a total per-scan time budget, concurrency caps, a capped port list, and an opt-in flag for port scanning.
- Authorization gate — the API rejects any scan where
authorizedis nottrue, and the UI requires an explicit confirmation checkbox. - Activity logging — scans are logged (start, rejection, completion).
To assess a lab host on private IP space, set ALLOW_PRIVATE_TARGETS=true — do
this only in an isolated environment you control.
Categories and default weights (all configurable via .env):
| Category | Weight |
|---|---|
| TLS configuration | 22% |
| HTTP security headers | 18% |
| Application layer | 14% |
| DNS & email security | 13% |
| Exposed services | 10% |
| Software/vulnerabilities | 18% |
| Other configuration | 5% |
Each category starts at 100 and loses points per finding. The overall score is the weighted average, mapped to a grade (A+/A/B/C/D/F) and a risk level (Critical/High/Medium/Low/Informational). Weights are normalized at load, so the tool still works if they don't sum to exactly 1.0.
Providers implement a common interface (VulnerabilityProvider.search) and can be
enabled/disabled individually. Included: OSV (free, keyless) and NVD (free;
optional NVD_API_KEY raises the rate limit), with CISA KEV enrichment. Each
provider has retries with exponential backoff, request timeouts, local file caching
(TTL configurable), graceful failure when a source is down, and source attribution
on every record. Nothing depends on a single external API, and no API keys are ever
hard-coded.
Rate limits: NVD allows ~5 requests / 30s without a key and ~50 with one; OSV is generous for occasional queries. The cache (default 24h) keeps usage well within these limits.
All settings are environment variables (see .env.example). Highlights:
| Variable | Default | Meaning |
|---|---|---|
ALLOW_PRIVATE_TARGETS |
false |
Permit private/loopback targets (lab use only) |
ENABLE_PORT_SCAN |
true |
Master switch for the opt-in port scan |
DEFAULT_PORTS |
common set | Ports scanned when none are specified |
NVD_API_KEY |
empty | Optional NVD key for higher rate limits |
GITHUB_TOKEN |
empty | Optional token for GitHub advisories |
TOTAL_SCAN_TIMEOUT |
180 |
Per-scan time budget (seconds) |
WEIGHT_* |
see file | Per-category scoring weights |
Never commit your .env — it is gitignored for this reason.
pytestAll external APIs are mocked (respx), so tests are hermetic. Coverage includes
TLS assessment and certificate quality, header analysis, application-layer checks
(cookies/CORS/CSP/HTTPS enforcement), DNS analysis, scoring, target validation and
SSRF protection, vulnerability-provider parsing, port-scan logic, the attack/tech
knowledge base, and API endpoints.
For integration testing against intentionally vulnerable environments, point the
tool at a lab you control (e.g. OWASP Juice Shop or a local badssl-style host) with
ALLOW_PRIVATE_TARGETS=true. Do not run integration scans against arbitrary
third-party sites.
- Put the app behind a reverse proxy (nginx/Caddy) terminating TLS.
- Set
DEBUG=falseand restrict CORS (the app already narrows CORS whenDEBUGis false). - Run the container as the provided non-root user (default in the Dockerfile).
- Swap the in-memory scan store in
services/scan_manager.pyfor Redis or a database if you need persistence or horizontal scaling. - Put authentication/authorization in front of the API so only permitted operators can launch scans.
- Keep
ALLOW_PRIVATE_TARGETS=falsein any internet-reachable deployment.
Add a scanner by creating a module in backend/scanners/ that returns
{"findings": [...], ...} and wiring it into services/scan_manager.py. Add a
vulnerability source by subclassing VulnerabilityProvider and registering it in
scanners/vulnerabilities.py.
This tool reports "a security weakness was detected," never "the target was exploited." Results reflect only the indicators tested here and are not a guarantee of security. Network results can be shaped by firewalls, NAT, CDNs and load balancers, and vulnerability correlation depends on accurate version disclosure and database coverage.
Issues and pull requests are welcome. Please:
- Keep the tool non-destructive — no exploitation, no payloads, no brute force.
- Add or update tests for any new scanner or logic (
pytestmust stay green). - Run the existing test suite before opening a PR.
Released under the MIT License. It is provided as-is, for authorized security assessment only. The authors accept no liability for misuse.

