Files
mukul975 c47eed6a64 Production hardening: security fixes, code quality, 724 skills complete
- Fix 25 shell=True subprocess calls with list-based commands
- Fix 49 verify=False in defensive skills (env-var override)
- Add timeout to 231 HTTP/subprocess/socket calls
- Fix 6 SQL injection patterns with whitelist validation
- Replace 8 __import__() with standard imports
- Remove 701 unused imports across 442 files
- Add authorized-testing disclaimers to all offensive skills
- Complete 11 incomplete skill directories
- Expand 10 stub SKILL.md files with full content
- Fix 2 YAML parse errors in frontmatter
- Fix 5 pre-existing syntax errors
- Convert 22 hardcoded paths/ports to environment variables
- Back up 21 redundant skill pairs to .bak
- Fix 2 global declaration errors
- 724/724 skills with full folder anatomy (SKILL.md + agent.py + api-reference.md + LICENSE)
- 0 compile errors across all 724 agent.py files
2026-03-19 13:26:49 +01:00

176 lines
6.7 KiB
Python

#!/usr/bin/env python3
"""Device posture assessment agent for zero trust endpoint compliance evaluation."""
import argparse
import json
import logging
import os
import platform
import subprocess
from datetime import datetime
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)
def check_os_version() -> dict:
"""Check OS version and patch level."""
return {
"os": platform.system(),
"version": platform.version(),
"release": platform.release(),
"machine": platform.machine(),
}
def check_disk_encryption() -> dict:
"""Check if disk encryption is enabled."""
system = platform.system()
if system == "Windows":
try:
result = subprocess.run(
["manage-bde", "-status", "C:"], capture_output=True, text=True, timeout=10)
encrypted = "Fully Encrypted" in result.stdout or "100%" in result.stdout
return {"enabled": encrypted, "tool": "BitLocker", "output": result.stdout[:200]}
except FileNotFoundError:
return {"enabled": False, "tool": "BitLocker", "error": "manage-bde not found"}
elif system == "Darwin":
try:
result = subprocess.run(
["fdesetup", "status"], capture_output=True, text=True, timeout=10)
return {"enabled": "On" in result.stdout, "tool": "FileVault"}
except FileNotFoundError:
return {"enabled": False, "error": "fdesetup not found"}
elif system == "Linux":
try:
result = subprocess.run(
["lsblk", "-o", "NAME,TYPE,FSTYPE"], capture_output=True, text=True, timeout=10)
encrypted = "crypto_LUKS" in result.stdout or "crypt" in result.stdout
return {"enabled": encrypted, "tool": "LUKS"}
except FileNotFoundError:
return {"enabled": False, "error": "lsblk not found"}
return {"enabled": False, "error": "Unsupported OS"}
def check_firewall_status() -> dict:
"""Check if host firewall is enabled."""
system = platform.system()
if system == "Windows":
try:
result = subprocess.run(
["netsh", "advfirewall", "show", "allprofiles", "state"],
capture_output=True, text=True, timeout=10)
enabled = "ON" in result.stdout.upper()
return {"enabled": enabled, "tool": "Windows Firewall"}
except FileNotFoundError:
return {"enabled": False, "error": "netsh not found"}
elif system == "Linux":
try:
result = subprocess.run(
["ufw", "status"], capture_output=True, text=True, timeout=10)
return {"enabled": "active" in result.stdout.lower(), "tool": "UFW"}
except FileNotFoundError:
return {"enabled": False, "error": "ufw not found"}
return {"enabled": False, "error": "Unsupported OS"}
def check_antivirus() -> dict:
"""Check if antivirus/EDR is running."""
system = platform.system()
if system == "Windows":
try:
result = subprocess.run(
["powershell", "-Command", "Get-MpComputerStatus | Select-Object RealTimeProtectionEnabled | ConvertTo-Json"],
capture_output=True, text=True, timeout=15)
if result.stdout:
data = json.loads(result.stdout)
return {"enabled": data.get("RealTimeProtectionEnabled", False),
"tool": "Windows Defender"}
except (FileNotFoundError, json.JSONDecodeError):
pass
return {"enabled": False, "tool": "unknown"}
def check_screen_lock() -> dict:
"""Check if screen lock is configured with timeout."""
system = platform.system()
if system == "Windows":
try:
result = subprocess.run(
["powershell", "-Command",
"(Get-ItemProperty 'HKLM:\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Policies\\System').InactivityTimeoutSecs"],
capture_output=True, text=True, timeout=10)
timeout = int(result.stdout.strip()) if result.stdout.strip() else 0
return {"configured": timeout > 0, "timeout_seconds": timeout}
except (FileNotFoundError, ValueError):
pass
return {"configured": False, "timeout_seconds": 0}
def compute_posture_score(checks: dict) -> dict:
"""Compute device posture compliance score."""
weights = {"disk_encryption": 25, "firewall": 20, "antivirus": 25,
"screen_lock": 15, "os_supported": 15}
score = 0
if checks.get("disk_encryption", {}).get("enabled"):
score += weights["disk_encryption"]
if checks.get("firewall", {}).get("enabled"):
score += weights["firewall"]
if checks.get("antivirus", {}).get("enabled"):
score += weights["antivirus"]
if checks.get("screen_lock", {}).get("configured"):
score += weights["screen_lock"]
score += weights["os_supported"]
if score >= 80:
compliance = "COMPLIANT"
elif score >= 50:
compliance = "PARTIAL"
else:
compliance = "NON_COMPLIANT"
return {"score": score, "max_score": 100, "compliance": compliance}
def generate_report() -> dict:
"""Generate device posture assessment report."""
checks = {
"os_info": check_os_version(),
"disk_encryption": check_disk_encryption(),
"firewall": check_firewall_status(),
"antivirus": check_antivirus(),
"screen_lock": check_screen_lock(),
}
posture = compute_posture_score(checks)
recommendations = []
if not checks["disk_encryption"].get("enabled"):
recommendations.append("Enable disk encryption (BitLocker/FileVault/LUKS)")
if not checks["firewall"].get("enabled"):
recommendations.append("Enable host firewall")
if not checks["antivirus"].get("enabled"):
recommendations.append("Enable antivirus/EDR with real-time protection")
return {
"analysis_date": datetime.utcnow().isoformat(),
"hostname": platform.node(),
"checks": checks,
"posture": posture,
"recommendations": recommendations,
}
def main():
parser = argparse.ArgumentParser(description="Device Posture Assessment Agent")
parser.add_argument("--output-dir", default=".")
parser.add_argument("--output", default="device_posture_report.json")
args = parser.parse_args()
os.makedirs(args.output_dir, exist_ok=True)
report = generate_report()
out_path = os.path.join(args.output_dir, args.output)
with open(out_path, "w") as f:
json.dump(report, f, indent=2)
logger.info("Report saved to %s", out_path)
print(json.dumps(report["posture"], indent=2))
if __name__ == "__main__":
main()