CLI-first Windows security misconfiguration auditor with weighted scoring, threat-intel enrichment, and multi-format reporting.
Project description
๐ก๏ธ WinSecAudit v2
A CLI-first Windows Security Misconfiguration Auditor
Weighted scoring ยท Threat intelligence enrichment ยท Multi-format reporting ยท Drift detection
โจ Overview
WinSecAudit v2 audits Windows 10/11 machines for common security misconfigurations, assigns a weighted risk score, enriches every finding with live CVE threat intelligence, and produces boardroom-ready reports in four formats. It's built as a plugin system โ every check is a self-contained class auto-discovered at runtime, so extending the suite requires zero wiring.
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ 39 CHECKS โ โโโถ โ SCORING โ โโโถ โ THREAT INTELโ โโโถ โ REPORTS โ
โ (PowerShell) โ โ (weighted) โ โ NVD+EPSS+KEV โ โ PDF/DOCX/CSV โ
โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ
๐ Table of Contents
- ๐ Quick Start
- โ๏ธ Installation
- ๐งฐ Commands
- ๐ Security Checks
- ๐๏ธ Profiles
- ๐ Scoring & Grading
- ๐ Threat Intelligence
- ๐ Output Formats
- ๐งช Testing
- โ ๏ธ Known Limitations
- ๐ Project Structure
- ๐ค Contributing
๐ Quick Start
# 1. Clone & install
git clone https://github.com/KavyaJain321/winsecaudit-v2.git
cd winsecaudit-v2
pip install -r requirements.txt
# 2. Run your first audit (open an elevated PowerShell first)
python winsecaudit.py scan
# 3. Export a beautiful PDF report
python winsecaudit.py report --format pdf
๐ก Tip: The SQLite database and all caches are created automatically on first run inside
data/. No setup scripts, no migrations.
โ๏ธ Installation
Requirements
| Requirement | Version |
|---|---|
| Python | 3.11 or newer |
| OS | Windows 10 / 11 (elevated shell for most checks) |
| Dependencies | See requirements.txt |
Setup
git clone https://github.com/KavyaJain321/winsecaudit-v2.git
cd winsecaudit-v2
pip install -r requirements.txt
Optional
# Set your NVD API key to bump rate limit from 5 โ 50 req/s
$env:NVD_API_KEY = "your-key-here" # PowerShell
export NVD_API_KEY="your-key-here" # Bash
๐งฐ Commands
WinSecAudit ships with 6 Typer-powered commands. Run python winsecaudit.py --help to see them all.
scan โ Run the full audit
python winsecaudit.py scan [OPTIONS]
| Option | Default | Description |
|---|---|---|
--profile |
basic |
Profile name (basic or hardened) |
--output |
terminal |
Output mode: terminal or json |
--no-threat-intel |
off | Skip NVD / EPSS / CISA KEV enrichment |
report โ Generate a formatted report
python winsecaudit.py report [OPTIONS]
| Option | Default | Description |
|---|---|---|
--scan-id |
latest | Specific scan ID to report on |
--format |
terminal |
terminal, pdf, docx, or csv |
list โ List saved scans
python winsecaudit.py list [--machine HOSTNAME] [--limit N]
drift โ Compare two scans
python winsecaudit.py drift [--scan-a ID] [--scan-b ID]
Defaults to comparing the two most recent scans. Under the hood, drift emulates a FULL OUTER JOIN with two LEFT JOINs + UNION ALL (SQLite doesn't support full outer joins natively).
fix โ List or apply remediations
python winsecaudit.py fix --list # show all remediable checks
python winsecaudit.py fix --check "Check Name" # apply the fix
dashboard โ Launch the FastAPI read-only dashboard
python winsecaudit.py dashboard
# Opens http://localhost:8080
๐ Security Checks
39 checks across 8 categories, all auto-discovered via CheckRegistry.discover():
| Category | # | Sample Checks |
|---|---|---|
| ๐ Authentication | 6 | Password complexity, min length, account lockout, guest account, admin rename |
| ๐ช Access Control | 5 | UAC level, admin shares, AutoRun, WSH, PowerShell execution policy |
| ๐ Network | 6 | SMBv1 disabled, LLMNR, NetBIOS, WPAD, RDP NLA, NTLMv1 |
| โ๏ธ Services | 5 | Print Spooler, Telnet, SNMP, FTP, WinRM |
| ๐งฌ Kernel | 4 | Secure Boot, DEP, ASLR, Kernel DMA Protection, VBS/HVCI |
| ๐ฅ๏ธ System | 5 | BitLocker, Defender, Firewall, Windows Update, Secure Boot |
| ๐ Logging | 4 | Audit policy, PowerShell module logging, script-block logging, Sysmon |
| ๐ Credentials | 4 | Credential Guard, LAPS, WDigest disabled, cached logons |
Each check emits an immutable CheckResult with CVE IDs, MITRE ATT&CK technique, CIS benchmark ID, severity, weight, and a ready-to-run remediation command.
๐๏ธ Profiles
Profiles live in profiles/*.yaml and control three levers:
| Key | Effect |
|---|---|
relaxed_checks |
Named checks whose FAIL is flipped to PASS (with a note). Use for controls intentionally disabled on a machine class. |
weight_overrides |
Override the default weight of any check by name. |
required_checks |
(Reserved) Checks that must pass for the scan to succeed. |
Bundled Profiles
| Profile | Target | Relaxations |
|---|---|---|
basic |
Workstations, developer machines | BitLocker, Secure Boot, NTLMv1, PS exec policy, Kernel DMA |
hardened |
Servers, high-security workstations | None โ all checks enforced with higher weights on crypto/creds |
๐ Scoring & Grading
score = (earned_weight / max_possible_weight) ร 100
| Status | Contribution |
|---|---|
| โ PASS | earns full check weight |
| โ FAIL / ERROR | earns 0 |
| โญ๏ธ SKIPPED | excluded from numerator and denominator |
Edge case: if every check is skipped โ
score = 100.0
Grade Bands
| Grade | Score Range | Meaning |
|---|---|---|
| ๐ข A | โฅ 90 | Excellent โ hardened baseline met |
| ๐ข B | โฅ 75 | Good โ minor gaps |
| ๐ก C | โฅ 60 | Acceptable โ remediation recommended |
| ๐ D | โฅ 40 | Poor โ significant exposure |
| ๐ด F | < 40 | Critical โ immediate action required |
๐ Threat Intelligence
Every CVE associated with a failed check is enriched from three sources:
| Source | Data | Rate Limit | Cache TTL |
|---|---|---|---|
| NIST NVD | CVSS score, severity, description | 5/s anon ยท 50/s with key | 7 days |
| FIRST EPSS | Exploitation probability (0.0โ1.0) | None documented | 7 days |
| CISA KEV | Known-exploited flag + ransomware use | Bulk download | 24 hours |
Caches live in data/cve_map.json and data/cisa_kev_cache.json. Enrichment degrades gracefully โ a 429 from NVD does not crash the scan; affected CVEs simply ship without TI metadata.
๐ Output Formats
| Format | File | Highlights |
|---|---|---|
| ๐ฅ๏ธ Terminal | (stdout) | Rich-rendered tables ยท ANSI colour ยท live progress |
| ๐ PDF | output/<scan_id>.pdf |
Cover page ยท executive summary ยท category breakdown ยท failure deep-dive ยท "Page N of M" footer |
| ๐ DOCX | output/<scan_id>.docx |
Word-native styles ยท FAIL rows bold + italic |
| ๐ CSV | output/<scan_id>.csv |
UTF-8 BOM ยท scan metadata denormalised per row (SIEM-friendly) |
๐งช Testing
python tests/smoke_test.py
10 standalone tests cover: imports, check discovery, profile loading, scoring math, grade thresholds, DB round-trip, profile relaxation, TI offline cache, CLI entry point, and the full pipeline. No pytest required โ exits 0 on success.
WinSecAudit v2 โ Smoke Tests
========================================
PASS 01 Import health
PASS 02 Check discovery
PASS 03 Profile loading
PASS 04 Scoring correctness
PASS 05 Grade thresholds
PASS 06 DB round-trip
PASS 07 Profile relaxation
PASS 08 TI cache offline-safe
PASS 09 CLI entry point
PASS 10 Full pipeline
========================================
Results: 10/10 passed
โ ๏ธ Known Limitations
- ๐ Elevation required โ Most PowerShell checks call
secedit,auditpol, or protected registry paths. Run from an elevated terminal. - ๐ช Windows-only checks โ All checks are PowerShell/Windows-specific. The DB, scoring engine, and exporters are cross-platform.
- ๐ NVD rate limit โ Without an API key, NVD allows 5 req/s. Set
NVD_API_KEYto raise this to 50 req/s. - ๐ฅ CISA KEV download โ First scan of the day downloads ~5 MB from
cisa.gov. Subsequent scans within 24 h use the cache.
๐ Project Structure
winsecaudit-v2/
โโโ winsecaudit.py # Entry point โ forces UTF-8 stdout/stderr on Windows
โโโ requirements.txt
โ
โโโ checks/ # ๐ Security check plugins (auto-discovered)
โ โโโ base.py # BaseCheck, CheckResult, CheckRegistry
โ โโโ auth/ # Authentication (6)
โ โโโ access/ # Access control (5)
โ โโโ network/ # Network (6)
โ โโโ services/ # Services (5)
โ โโโ kernel/ # Kernel/hardware (4)
โ โโโ system/ # System config (5)
โ โโโ logging/ # Audit & logging (4)
โ โโโ credentials/ # Credential protection (4)
โ
โโโ engine/ # โ๏ธ Core orchestration
โ โโโ runner.py # Parallel check execution
โ โโโ scorer.py # Weighted scoring
โ โโโ comparator.py # Profile loading & adjustment
โ โโโ risk.py # Grade assignment & priority
โ โโโ threat_intel.py # NVD / EPSS / CISA KEV pipeline
โ
โโโ db/ # ๐พ Persistence
โ โโโ database.py # SQLAlchemy Core layer
โ โโโ schema.sql # Reference DDL
โ
โโโ cli/ # ๐งฐ CLI surface
โ โโโ main.py # Typer commands
โ โโโ output.py # Rich rendering
โ
โโโ dashboard/ # ๐ FastAPI read-only dashboard
โ โโโ app.py
โ โโโ models.py
โ โโโ static/index.html
โ
โโโ exporters/ # ๐ Report generators
โ โโโ pdf.py # reportlab Platypus
โ โโโ docx_export.py # python-docx
โ โโโ csv_export.py # csv module
โ
โโโ profiles/ # ๐๏ธ YAML profiles
โ โโโ basic.yaml
โ โโโ hardened.yaml
โ
โโโ data/ # ๐๏ธ Runtime data (gitignored)
โโโ tests/
โโโ smoke_test.py # โ
10 standalone smoke tests
๐ค Contributing
Adding a new check is a three-step affair:
- Create a file under the appropriate
checks/<category>/directory. - Subclass
BaseCheckand set the class attributes (name,category,weight,severity,cve_ids,mitre_technique,cis_id,remediation_cmd,remediation_supported). - Implement
run() -> CheckResult. That's it โCheckRegistry.discover()picks it up on the next scan.
from checks.base import BaseCheck, CheckResult, CheckStatus, Severity, run_powershell
class MyNewCheck(BaseCheck):
name = "My New Check"
category = "System"
weight = 5
severity = Severity.HIGH
remediation_cmd = "Set-ItemProperty ..."
remediation_supported = True
def run(self) -> CheckResult:
value = run_powershell("Get-Something")
return CheckResult(
check_name=self.name,
category=self.category,
status=CheckStatus.PASS if value == "expected" else CheckStatus.FAIL,
system_value=value,
expected_value="expected",
severity=self.severity,
weight=self.weight,
cve_ids=(),
mitre_technique="",
cis_id="",
remediation_cmd=self.remediation_cmd,
remediation_supported=self.remediation_supported,
)
Built with โค๏ธ for defenders.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file winsecaudit-1.1.2.tar.gz.
File metadata
- Download URL: winsecaudit-1.1.2.tar.gz
- Upload date:
- Size: 165.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb9e3cecfd52a879892f6549441dc31877e297d9dcef1c246930231607628945
|
|
| MD5 |
057cec5e4c0b3cd6a307a18420e96d45
|
|
| BLAKE2b-256 |
36f1c95039e4649faf755ae43890309a5103912ee9bcad01b63f96bb144ab180
|
File details
Details for the file winsecaudit-1.1.2-py3-none-any.whl.
File metadata
- Download URL: winsecaudit-1.1.2-py3-none-any.whl
- Upload date:
- Size: 208.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
865b59e9ff56c5c1ea26bbbce703777c366a29537420d58646e62e659be09484
|
|
| MD5 |
23ab05066b5590a739ec160ddc89127c
|
|
| BLAKE2b-256 |
d5e6ade752f301b0df639df61a2a0e996e9f0bac04ae238853324799c16f4b3a
|