From b736888f076c93748f1f21d968e71770ce479d97 Mon Sep 17 00:00:00 2001 From: Naman Singh Date: Tue, 7 Jul 2026 09:44:56 +0530 Subject: [PATCH] fix: enable TLS certificate verification across all scanners and crawler SECUSCAN-001 (Critical): TLS certificate verification was globally disabled with verify=False in 4 locations (crawler, XSS scanner, API scanner, network vulnerability scanner), leaving all outbound HTTPS connections vulnerable to MITM attacks. Added verify_ssl: bool = True to Settings (configurable via SECUSCAN_VERIFY_SSL env var) and updated all httpx.AsyncClient calls to reference it. --- backend/secuscan/config.py | 1 + backend/secuscan/crawler.py | 4 +++- backend/secuscan/scanners/api_scanner.py | 3 ++- backend/secuscan/scanners/network_vulnerability_scanner.py | 3 ++- backend/secuscan/scanners/xss_validation_scanner.py | 3 ++- 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/backend/secuscan/config.py b/backend/secuscan/config.py index 78e733fcf..0e0471aec 100644 --- a/backend/secuscan/config.py +++ b/backend/secuscan/config.py @@ -38,6 +38,7 @@ class Settings(BaseSettings): # Security safe_mode_default: bool = True + verify_ssl: bool = True dns_resolution_timeout_seconds: float = 1.5 dns_cache_ttl_seconds: int = 60 dns_rebind_check: bool = True diff --git a/backend/secuscan/crawler.py b/backend/secuscan/crawler.py index 183a50d30..7013184af 100644 --- a/backend/secuscan/crawler.py +++ b/backend/secuscan/crawler.py @@ -9,6 +9,8 @@ import httpx +from .config import settings + class _SurfaceParser(HTMLParser): def __init__(self) -> None: @@ -86,7 +88,7 @@ async def crawl_target( timeout=timeout, headers=headers, cookies=cookies or {}, - verify=False, + verify=settings.verify_ssl, ) as client: response = await client.get(url) diff --git a/backend/secuscan/scanners/api_scanner.py b/backend/secuscan/scanners/api_scanner.py index d3ed5a6d6..1cef1d076 100644 --- a/backend/secuscan/scanners/api_scanner.py +++ b/backend/secuscan/scanners/api_scanner.py @@ -6,6 +6,7 @@ import httpx +from ..config import settings from .base import BaseScanner from ..crawler import crawl_target @@ -52,7 +53,7 @@ async def run(self, target: str, inputs: Dict[str, Any]) -> Dict[str, Any]: timeout=timeout, headers={str(k): str(v) for k, v in extra_headers.items()}, cookies={str(k): str(v) for k, v in cookies.items()}, - verify=False, + verify=settings.verify_ssl, ) as client: for path in self.COMMON_SPEC_PATHS: url = urljoin(target.rstrip("/") + "/", path.lstrip("/")) diff --git a/backend/secuscan/scanners/network_vulnerability_scanner.py b/backend/secuscan/scanners/network_vulnerability_scanner.py index cc0371d5f..b4a9cac41 100644 --- a/backend/secuscan/scanners/network_vulnerability_scanner.py +++ b/backend/secuscan/scanners/network_vulnerability_scanner.py @@ -8,6 +8,7 @@ import httpx +from ..config import settings from .base import BaseScanner from ..knowledgebase import KnowledgeBase from ..plugins import get_plugin_manager @@ -186,7 +187,7 @@ async def _probe_http(self, host: str, port: int, *, tls: bool) -> Optional[Dict scheme = "https" if tls else "http" url = f"{scheme}://{host}:{port}/" try: - async with httpx.AsyncClient(follow_redirects=True, timeout=5, verify=False) as client: + async with httpx.AsyncClient(follow_redirects=True, timeout=5, verify=settings.verify_ssl) as client: response = await client.get(url) except Exception: return None diff --git a/backend/secuscan/scanners/xss_validation_scanner.py b/backend/secuscan/scanners/xss_validation_scanner.py index 7e806f3ec..a66ae0308 100644 --- a/backend/secuscan/scanners/xss_validation_scanner.py +++ b/backend/secuscan/scanners/xss_validation_scanner.py @@ -6,6 +6,7 @@ import httpx +from ..config import settings from .base import BaseScanner @@ -28,7 +29,7 @@ async def run(self, target: str, inputs: Dict[str, Any]) -> Dict[str, Any]: findings: List[Dict[str, Any]] = [] self.update_progress(0.25) - async with httpx.AsyncClient(follow_redirects=True, timeout=int(inputs.get("timeout") or 10), verify=False) as client: + async with httpx.AsyncClient(follow_redirects=True, timeout=int(inputs.get("timeout") or 10), verify=settings.verify_ssl) as client: response = await client.get(probe_url) body = response.text