# app/modules/prospecting/services/security_report_service.py """ Generate branded HTML security audit reports from stored audit data. Produces a standalone HTML document suitable for viewing in a browser, printing to PDF, or emailing to prospects. Reports include: - Security grade and score - "What could happen" fear section with simulated hacked site - Detailed findings grouped by category - Business impact summary - Call to action with contact info """ import html as html_module import json import logging from datetime import datetime from app.modules.prospecting.models import ProspectSecurityAudit logger = logging.getLogger(__name__) SEVERITY_COLORS = { "critical": ("#dc2626", "#fef2f2", "#991b1b"), "high": ("#ea580c", "#fff7ed", "#9a3412"), "medium": ("#ca8a04", "#fefce8", "#854d0e"), "low": ("#2563eb", "#eff6ff", "#1e40af"), "info": ("#6b7280", "#f9fafb", "#374151"), } GRADE_COLORS = { "A+": "#16a34a", "A": "#22c55e", "B": "#eab308", "C": "#f97316", "D": "#ef4444", "F": "#991b1b", } CATEGORY_LABELS = { "transport": "Transport Security (HTTPS/SSL)", "headers": "Security Headers", "exposure": "Information Exposure", "cookies": "Cookie Security", "config": "Server Configuration", "technology": "Technology & Versions", } DEFAULT_CONTACT = { "name": "Samir Boulahtit", "email": "contact@wizard.lu", "phone": "+352 XXX XXX XXX", "company": "Wizard", "website": "https://wizard.lu", "tagline": "Professional Web Development & Security", } class SecurityReportService: """Generate branded HTML security audit reports.""" def generate_html_report( self, audit: ProspectSecurityAudit, domain: str, contact: dict | None = None, ) -> str: """Generate a standalone HTML report from stored audit data.""" contact = contact or DEFAULT_CONTACT esc = html_module.escape findings = json.loads(audit.findings_json) if audit.findings_json else [] technologies = json.loads(audit.technologies_json) if audit.technologies_json else [] grade = audit.grade score = audit.score grade_color = GRADE_COLORS.get(grade, "#6b7280") # Severity counts sev_counts = {"critical": 0, "high": 0, "medium": 0, "low": 0} for f in findings: if not f.get("is_positive") and f["severity"] in sev_counts: sev_counts[f["severity"]] += 1 # Group findings by category categories = ["transport", "headers", "exposure", "cookies", "config", "technology"] grouped = {cat: [f for f in findings if f["category"] == cat] for cat in categories} # Build findings HTML findings_html = "" for cat in categories: cat_findings = grouped.get(cat, []) if not cat_findings: continue label = CATEGORY_LABELS.get(cat, cat) findings_html += f'
This is a simulation based on real-world attacks. With the vulnerabilities found on your site, this scenario is technically possible.
Every day these vulnerabilities remain unfixed is another day your business and your customers are at risk.
Contact us today for a free consultation:
This report was generated using passive, non-intrusive analysis techniques only. No active exploitation or unauthorized access was attempted.
© {datetime.now().year} {esc(contact['company'])} — {esc(contact['tagline'])}