diff --git a/.github/workflows/coverage.yml b/.github/workflows/coverage.yml index ec94048..de7c1bd 100644 --- a/.github/workflows/coverage.yml +++ b/.github/workflows/coverage.yml @@ -7,6 +7,9 @@ on: branches: [ main ] workflow_dispatch: +permissions: + contents: read + jobs: coverage: runs-on: ubuntu-latest diff --git a/docksec/cli.py b/docksec/cli.py index b1c5fcc..ccdb8c3 100644 --- a/docksec/cli.py +++ b/docksec/cli.py @@ -3,7 +3,6 @@ import sys import os import argparse -from typing import Optional def get_version() -> str: """Return the installed package version. @@ -23,7 +22,7 @@ def get_version() -> str: import re setup_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'setup.py') with open(setup_path, 'r') as f: - match = re.search(r'version="([^"]+)"', f.read()) + match = re.search(r'version\s*=\s*["\']([^"\']+)["\']', f.read()) if match: return match.group(1) except Exception: # setup.py missing or unreadable; fall through to unknown @@ -81,8 +80,7 @@ def main() -> None: # Validate image requirement for image-based operations if (args.image_only or args.scan_only) and not args.image: - operation = "image-only scanning" if args.image_only else "scan-only mode" - print(f"Error: Image name is required for {operation}. Use -i/--image to specify the Docker image.") + print(f"Error: Image name is required for {'image-only scanning' if args.image_only else 'scan-only mode'}. Use -i/--image to specify the Docker image.") print("Example: docksec --image-only -i myapp:latest") sys.exit(1) @@ -124,7 +122,6 @@ def main() -> None: from pathlib import Path # Set up the same components as main.py - logger = get_custom_logger(name='docksec_ai') llm = get_llm() Report_llm = llm.with_structured_output(AnalyzesResponse, method="json_mode") analyser_chain = docker_agent_prompt | Report_llm diff --git a/docksec/config_manager.py b/docksec/config_manager.py index e94915d..9bb6cf5 100644 --- a/docksec/config_manager.py +++ b/docksec/config_manager.py @@ -8,8 +8,7 @@ import os import logging -from pathlib import Path -from typing import Optional, Dict, Any +from typing import Optional, Any, Dict from dataclasses import dataclass, field # Set up logger diff --git a/docksec/docker_scanner.py b/docksec/docker_scanner.py index 309327f..0f68c67 100644 --- a/docksec/docker_scanner.py +++ b/docksec/docker_scanner.py @@ -9,8 +9,7 @@ import sys import re from pathlib import Path -from docksec.config import RESULTS_DIR -from docksec.config import docker_score_prompt +from docksec.config import RESULTS_DIR, docker_score_prompt from docksec.utils import ScoreResponse, get_llm, print_section, get_custom_logger # Initialize logger @@ -158,7 +157,7 @@ def __init__(self, dockerfile_path: str, image_name: str, results_dir: str = RES # Verify Docker image exists (using validated image_name) try: - result = subprocess.run( + subprocess.run( ['docker', 'image', 'inspect', self.image_name], capture_output=True, check=True, @@ -1051,8 +1050,6 @@ def save_results_to_html(self, results: Dict) -> str: # 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') try: from docksec.config import html_template diff --git a/docksec/report_generator.py b/docksec/report_generator.py index f9dcd67..1928178 100644 --- a/docksec/report_generator.py +++ b/docksec/report_generator.py @@ -19,7 +19,6 @@ from typing import Dict, List, Optional from datetime import datetime from fpdf import FPDF -from pathlib import Path from docksec.config import RESULTS_DIR, html_template from docksec.utils import get_custom_logger diff --git a/docksec/score_calculator.py b/docksec/score_calculator.py index b8a2248..ee37a51 100644 --- a/docksec/score_calculator.py +++ b/docksec/score_calculator.py @@ -5,8 +5,6 @@ It uses LLM-based analysis to provide comprehensive security scoring. """ -import logging -import re from typing import Dict from docksec.config import docker_score_prompt from docksec.utils import ScoreResponse, get_llm, get_custom_logger diff --git a/docksec/setup_external_tools.py b/docksec/setup_external_tools.py index e5b9717..2988596 100644 --- a/docksec/setup_external_tools.py +++ b/docksec/setup_external_tools.py @@ -1,13 +1,12 @@ #!/usr/bin/env python3 import subprocess -import sys import os import platform import shutil +import zipfile from pathlib import Path import urllib.request import stat -import zipfile import json def get_os_type(): @@ -117,7 +116,6 @@ def install_trivy(): # Download URL for Windows url = f"https://github.com/aquasecurity/trivy/releases/download/v{version}/trivy_{version}_windows-64bit.zip" zip_path = install_dir / "trivy.zip" - exe_path = install_dir / "trivy.exe" # Download and extract print(f"Downloading Trivy v{version}...") diff --git a/docksec/utils.py b/docksec/utils.py index 4a80c08..9ea3ed7 100644 --- a/docksec/utils.py +++ b/docksec/utils.py @@ -1,7 +1,8 @@ import logging import sys import os -from typing import Union +import time +from typing import Union, List, Optional # Import OpenAI (required) try: @@ -43,12 +44,9 @@ "Either 'pydantic' or 'langchain-core' must be installed. " "Install with: pip install pydantic langchain-core" ) -from typing import List, Optional -import time from tqdm import tqdm from colorama import Fore, Style, init from rich.console import Console -from rich.table import Table from tenacity import ( retry, stop_after_attempt, diff --git a/requirements.txt b/requirements.txt index d1bf339..54c75e9 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,11 @@ # Core dependencies - pinned to specific versions for fast, reliable installs pydantic==2.13.4 -langchain-core==0.3.26 -langchain==0.3.13 -langchain-openai==0.2.10 -langchain-anthropic==0.3.0 -langchain-google-genai==2.0.5 -langchain-ollama==0.2.0 +langchain-core==1.3.3 +langchain==1.2.18 +langchain-openai==1.2.1 +langchain-anthropic==1.4.3 +langchain-google-genai==4.2.2 +langchain-ollama==1.1.0 python-dotenv==1.2.2 pandas==3.0.2 diff --git a/setup.py b/setup.py index 032644b..141977a 100644 --- a/setup.py +++ b/setup.py @@ -5,7 +5,7 @@ setup( name="docksec", - version="2026.5.6", + version="2026.5.15", description="AI-Powered Docker Security Analyzer", long_description=long_description, long_description_content_type="text/markdown", @@ -25,12 +25,12 @@ python_requires=">=3.12", install_requires=[ "pydantic==2.13.4", - "langchain-core==0.3.26", - "langchain==0.3.13", - "langchain-openai==0.2.10", - "langchain-anthropic==0.3.0", - "langchain-google-genai==2.0.5", - "langchain-ollama==0.2.0", + "langchain-core==1.3.3", + "langchain==1.2.18", + "langchain-openai==1.2.1", + "langchain-anthropic==1.4.3", + "langchain-google-genai==4.2.2", + "langchain-ollama==1.1.0", "python-dotenv==1.2.2", "pandas==3.0.2", "tqdm==4.67.3", diff --git a/tests/test_docker_scanner.py b/tests/test_docker_scanner.py index 438286b..ed062b4 100644 --- a/tests/test_docker_scanner.py +++ b/tests/test_docker_scanner.py @@ -109,7 +109,7 @@ def test_check_tools_missing(self, mock_subprocess): # Mock FileNotFoundError for missing tool mock_subprocess.side_effect = FileNotFoundError() - dockerfile = self.create_test_dockerfile() + self.create_test_dockerfile() with patch('docksec.docker_scanner.get_llm'): scanner = DockerSecurityScanner.__new__(DockerSecurityScanner)