1+ import os
2+ import google .generativeai as genai
3+ from pathlib import Path
4+
5+ # Configure Gemini
6+ API_KEY = os .getenv ("GEMINI_API_KEY" )
7+ if not API_KEY :
8+ raise ValueError ("GEMINI_API_KEY environment variable not set" )
9+
10+ genai .configure (api_key = API_KEY )
11+
12+ # Configuration
13+ MODEL_NAME = "gemini-1.5-pro-latest" # Using 1.5 Pro for large context window
14+ ROOT_DIR = "."
15+ OUTPUT_FILE = "SECURITY_REPORT.md"
16+
17+ # Extensions to scan
18+ INCLUDED_EXTENSIONS = {".java" , ".gradle" , ".xml" , ".sh" , ".properties" }
19+ EXCLUDED_DIRS = {".git" , ".gradle" , "build" , "target" , ".idea" , "wrapper" }
20+
21+ def get_code_context (root_dir ):
22+ code_content = ""
23+ file_count = 0
24+
25+ for root , dirs , files in os .walk (root_dir ):
26+ # Filter directories
27+ dirs [:] = [d for d in dirs if d not in EXCLUDED_DIRS ]
28+
29+ for file in files :
30+ file_path = Path (root ) / file
31+ if file_path .suffix in INCLUDED_EXTENSIONS :
32+ try :
33+ with open (file_path , "r" , encoding = "utf-8" ) as f :
34+ content = f .read ()
35+ code_content += f"\n --- START FILE: { file_path } ---\n "
36+ code_content += content
37+ code_content += f"\n --- END FILE: { file_path } ---\n "
38+ file_count += 1
39+ except Exception as e :
40+ print (f"Skipping file { file_path } : { e } " )
41+
42+ print (f"Scanned { file_count } files." )
43+ return code_content
44+
45+ def analyze_code (code_context ):
46+ model = genai .GenerativeModel (MODEL_NAME )
47+
48+ prompt = f"""
49+ You are an expert Static Application Security Testing (SAST) tool and Senior Software Engineer.
50+ Analyze the following codebase for:
51+ 1. Security Vulnerabilities (OWASP Top 10, Injection, XSS, etc.)
52+ 2. Code Smells & Anti-patterns
53+ 3. Performance Issues
54+ 4. Dependency checks (based on build.gradle)
55+
56+ Format your response as a professional Markdown report with the following sections:
57+ - **Executive Summary**: High-level overview of health.
58+ - **Critical Vulnerabilities**: Immediate security threats.
59+ - **Code Quality Issues**: Maintainability and logic suggestions.
60+ - **Recommendations**: Specific code fixes.
61+
62+ Here is the codebase:
63+ { code_context }
64+ """
65+
66+ # Generate content
67+ # Set safety settings to block none to ensure we get the full critique even if code is "unsafe"
68+ response = model .generate_content (
69+ prompt ,
70+ generation_config = {"temperature" : 0.2 }
71+ )
72+
73+ return response .text
74+
75+ def main ():
76+ print ("Gathering code..." )
77+ code_context = get_code_context (ROOT_DIR )
78+
79+ print ("Sending to Gemini for analysis..." )
80+ report = analyze_code (code_context )
81+
82+ with open (OUTPUT_FILE , "w" , encoding = "utf-8" ) as f :
83+ f .write (report )
84+ print (f"Report generated: { OUTPUT_FILE } " )
85+
86+ if __name__ == "__main__" :
87+ main ()
0 commit comments