from __future__ import annotations from dataclasses import dataclass from typing import Dict, List, Optional @dataclass class FrameworkMapping: """ Mapping between a WAF concept (e.g. 'SQLi protection') and references in one or more compliance frameworks. """ control_id: str framework: str # e.g. "PCI-DSS", "NIST-800-53", "GDPR" description: str references: List[str] class ComplianceMapper: """ Map WAF rules / violations to compliance frameworks. This starts as a simple static lookup table that we can extend over time. """ def __init__(self) -> None: self._mappings: Dict[str, List[FrameworkMapping]] = self._build_default_mappings() def _build_default_mappings(self) -> Dict[str, List[FrameworkMapping]]: return { "sqli_protection": [ FrameworkMapping( control_id="6.6", framework="PCI-DSS", description="Ensure web-facing applications are protected against attacks such as SQL injection.", references=["PCI-DSS v4.0 6.6", "OWASP Top 10 - A03:2021"], ) ], "xss_protection": [ FrameworkMapping( control_id="A5", framework="OWASP-ASVS", description="Verify that all user-controllable input is properly encoded or escaped.", references=["OWASP Top 10 - A3: Cross-Site Scripting"], ) ], "baseline_waf": [ FrameworkMapping( control_id="13", framework="OWASP-ASVS", description="Centralized input validation, filtering, and WAF as compensating control.", references=["OWASP-ASVS 13", "PCI-DSS 6.4.1"], ) ], } def map_concept(self, concept: str) -> List[FrameworkMapping]: """ Map a high-level WAF concept to compliance controls. Example concepts: - "sqli_protection" - "xss_protection" - "baseline_waf" """ return self._mappings.get(concept, []) def best_effort_from_violation(self, message: str) -> List[FrameworkMapping]: """ Try to infer framework mappings from a violation message string. This allows the analyzer to stay dumb while still attaching controls. """ msg = message.lower() if "sql" in msg and "inject" in msg: return self.map_concept("sqli_protection") if "xss" in msg or "cross-site scripting" in msg: return self.map_concept("xss_protection") if "waf" in msg or "managed rules" in msg: return self.map_concept("baseline_waf") return []