From c1ebcf78e12a8907f250b37fd6fc9d165b3723db Mon Sep 17 00:00:00 2001 From: Dharshukutti Date: Sat, 15 Aug 2026 11:43:41 +0530 Subject: [PATCH] fix: track failed compose service scans --- docksec/compose_scanner.py | 38 ++++++++++++++++++++++++++++++----- tests/test_compose_scanner.py | 3 ++- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/docksec/compose_scanner.py b/docksec/compose_scanner.py index 3e82b58..b8c6691 100644 --- a/docksec/compose_scanner.py +++ b/docksec/compose_scanner.py @@ -383,7 +383,8 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: 'timestamp': "", 'image_name': "N/A", 'dockerfile_path': self.compose_path, - 'scan_mode': 'compose' + 'scan_mode': 'compose', + 'failed_services': [] } compose_findings = self.scanner.scan() @@ -394,6 +395,7 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: dockerfile_outputs = [] image_outputs = [] all_success = True + failed_services = [] for service_name, config in services.items(): if not isinstance(config, dict): @@ -441,6 +443,10 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: df_success, df_output = service_scanner.scan_dockerfile() if not df_success: all_success = False + failed_services.append({ + "service": service_name, + "reason": "Dockerfile scan failed" + }) if df_output: dockerfile_outputs.append(f"--- Service: {service_name} ---\n{df_output}") elif image_name and not dockerfile_path: @@ -448,6 +454,10 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: res = service_scanner.run_image_only_scan(severity) if not res['image_scan']['success']: all_success = False + failed_services.append({ + "service": service_name, + "reason": "Image scan failed" + }) if res['image_scan']['output']: image_outputs.append(f"--- Service: {service_name} ---\n{res['image_scan']['output']}") if res.get('json_data'): @@ -460,9 +470,22 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: res = service_scanner.run_full_scan(severity) if not res['dockerfile_scan']['success'] or not res['image_scan']['success']: all_success = False - if res['dockerfile_scan']['output'] and not res['dockerfile_scan'].get('skipped'): - dockerfile_outputs.append(f"--- Service: {service_name} ---\n{res['dockerfile_scan']['output']}") - if res['image_scan']['output'] and not res['image_scan'].get('skipped'): + + if not res['dockerfile_scan']['success']: + failed_services.append({ + "service": service_name, + "reason": "Dockerfile scan failed" + }) + + if not res['image_scan']['success']: + failed_services.append({ + "service": service_name, + "reason": "Image scan failed" + }) + + if res['dockerfile_scan'].get('output') and not res['dockerfile_scan'].get('skipped'): + dockerfile_outputs.append(f"--- Service: {service_name} ---\n{res['dockerfile_scan']['output']}") # type: ignore + if res['image_scan'].get('output') and not res['image_scan'].get('skipped'): image_outputs.append(f"--- Service: {service_name} ---\n{res['image_scan']['output']}") if res.get('json_data'): for f in res['json_data']: @@ -471,6 +494,10 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: except Exception as e: logger.error(f"Failed to scan service {service_name}: {e}") all_success = False + failed_services.append({ + "service": service_name, + "reason": str(e) + }) from datetime import datetime return { @@ -488,5 +515,6 @@ def run_full_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: 'timestamp': datetime.now().strftime("%Y-%m-%d %H:%M:%S"), 'image_name': "Multiple Services", 'dockerfile_path': self.compose_path, - 'scan_mode': 'compose' + 'scan_mode': 'compose', + 'failed_services': failed_services } diff --git a/tests/test_compose_scanner.py b/tests/test_compose_scanner.py index c540b37..54f065c 100644 --- a/tests/test_compose_scanner.py +++ b/tests/test_compose_scanner.py @@ -172,4 +172,5 @@ def test_compose_orchestrator_offline(valid_compose_file, mocker): assert results['scan_mode'] == 'compose' assert results['dockerfile_scan']['success'] is True - assert results['image_scan']['success'] is True + assert results['image_scan']['success'] is True + assert results["failed_services"] == [] \ No newline at end of file