From e3d1990ba56b56f62cfb25de8f3a50256aa04320 Mon Sep 17 00:00:00 2001 From: Advait Patel Date: Fri, 31 Oct 2025 22:24:53 -0500 Subject: [PATCH] Fix: Remove hardcoded sudo from Docker command - Removed hardcoded `sudo` from the `docker image inspect` command - Added comprehensive error handling for permission issues - Provides helpful, actionable error messages when Docker access fails - Handles edge cases (Docker not installed, daemon not running, permission denied) --- .gitignore | 3 +++ docker_scanner.py | 41 +++++++++++++++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/.gitignore b/.gitignore index 593023a..8c751f3 100644 --- a/.gitignore +++ b/.gitignore @@ -176,4 +176,7 @@ cython_debug/ testfiles/1/Dockerfile results/ +# Private code review and improvement tracking (not for public repository) +CODE_REVIEW_AND_IMPROVEMENTS.md + diff --git a/docker_scanner.py b/docker_scanner.py index 1885c86..77a574c 100644 --- a/docker_scanner.py +++ b/docker_scanner.py @@ -52,13 +52,30 @@ def __init__(self, dockerfile_path: str, image_name: str, results_dir: str = RES # Verify Docker image exists try: - subprocess.run( - ['sudo','docker', 'image', 'inspect', image_name], + result = subprocess.run( + ['docker', 'image', 'inspect', image_name], capture_output=True, - check=True + check=True, + text=True ) - except subprocess.CalledProcessError: + except subprocess.CalledProcessError as e: + # Check if the error is due to permission issues + error_output = e.stderr.lower() if e.stderr else "" + if "permission denied" in error_output or "cannot connect to the docker daemon" in error_output: + raise ValueError( + f"Unable to access Docker. This may require elevated permissions.\n" + f"Possible solutions:\n" + f" 1. Add your user to the docker group: sudo usermod -aG docker $USER (then log out and back in)\n" + f" 2. Ensure Docker daemon is running: sudo systemctl start docker (Linux) or start Docker Desktop\n" + f" 3. If you must use sudo, run DockSec with sudo (not recommended for security reasons)\n" + f"Original error: {e.stderr.strip() if e.stderr else str(e)}" + ) + # If it's not a permission error, assume the image doesn't exist raise ValueError(f"Docker image '{image_name}' not found locally") + except FileNotFoundError: + raise ValueError( + "Docker command not found. Please ensure Docker is installed and accessible in your PATH." + ) def run_image_only_scan(self, severity: str = "CRITICAL,HIGH") -> Dict: """ Run image-only security scan without Dockerfile analysis. @@ -356,7 +373,9 @@ def save_results_to_json(self, results: Dict) -> str: Returns: Path to the saved JSON file """ - output_file = os.path.join(self.RESULTS_DIR, f"{re.sub(r'[:/.\-]', '_', self.image_name)}_scan_results.json") + # Sanitize image name for filename (avoid backslash in f-string expression) + safe_image_name = re.sub(r'[:/.\-]', '_', self.image_name) + output_file = os.path.join(self.RESULTS_DIR, f"{safe_image_name}_scan_results.json") json_results = results.get('json_data', []) vulnerabilities = { @@ -388,7 +407,9 @@ def save_results_to_csv(self, results: Dict) -> str: Returns: Path to the saved CSV file """ - output_file = os.path.join(self.RESULTS_DIR, f"{re.sub(r'[:/.\-]', '_', self.image_name)}_vulnerabilities.csv") + # Sanitize image name for filename + safe_image_name = re.sub(r'[:/.\-]', '_', self.image_name) + output_file = os.path.join(self.RESULTS_DIR, f"{safe_image_name}_vulnerabilities.csv") vulnerabilities = results.get('json_data', []) if not vulnerabilities: @@ -428,7 +449,9 @@ def save_results_to_pdf(self, results: Dict) -> str: Returns: Path to the saved PDF file """ - output_file = os.path.join(self.RESULTS_DIR, f"{re.sub(r'[:/.\-]', '_', self.image_name)}_security_report.pdf") + # Sanitize image name for filename + safe_image_name = re.sub(r'[:/.\-]', '_', self.image_name) + output_file = os.path.join(self.RESULTS_DIR, f"{safe_image_name}_security_report.pdf") try: # Create custom PDF class with text wrapping capability @@ -683,7 +706,9 @@ def save_results_to_html(self, results: Dict) -> str: Returns: Path to the saved HTML file """ - output_file = os.path.join(self.RESULTS_DIR, f"{re.sub(r'[:/.\-]', '_', self.image_name)}_security_report.html") + # Sanitize image name for filename + safe_image_name = re.sub(r'[:/.\-]', '_', self.image_name) + output_file = os.path.join(self.RESULTS_DIR, f"{safe_image_name}_security_report.html") # template_path = os.path.join(os.path.dirname(__file__), 'templates', 'report_template.html') template_path = os.path.join(os.path.dirname(__file__), 'report_template.html')