aiptx 2.0.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- aipt_v2/__init__.py +110 -0
- aipt_v2/__main__.py +24 -0
- aipt_v2/agents/AIPTxAgent/__init__.py +10 -0
- aipt_v2/agents/AIPTxAgent/aiptx_agent.py +211 -0
- aipt_v2/agents/__init__.py +46 -0
- aipt_v2/agents/base.py +520 -0
- aipt_v2/agents/exploit_agent.py +688 -0
- aipt_v2/agents/ptt.py +406 -0
- aipt_v2/agents/state.py +168 -0
- aipt_v2/app.py +957 -0
- aipt_v2/browser/__init__.py +31 -0
- aipt_v2/browser/automation.py +458 -0
- aipt_v2/browser/crawler.py +453 -0
- aipt_v2/cli.py +2933 -0
- aipt_v2/compliance/__init__.py +71 -0
- aipt_v2/compliance/compliance_report.py +449 -0
- aipt_v2/compliance/framework_mapper.py +424 -0
- aipt_v2/compliance/nist_mapping.py +345 -0
- aipt_v2/compliance/owasp_mapping.py +330 -0
- aipt_v2/compliance/pci_mapping.py +297 -0
- aipt_v2/config.py +341 -0
- aipt_v2/core/__init__.py +43 -0
- aipt_v2/core/agent.py +630 -0
- aipt_v2/core/llm.py +395 -0
- aipt_v2/core/memory.py +305 -0
- aipt_v2/core/ptt.py +329 -0
- aipt_v2/database/__init__.py +14 -0
- aipt_v2/database/models.py +232 -0
- aipt_v2/database/repository.py +384 -0
- aipt_v2/docker/__init__.py +23 -0
- aipt_v2/docker/builder.py +260 -0
- aipt_v2/docker/manager.py +222 -0
- aipt_v2/docker/sandbox.py +371 -0
- aipt_v2/evasion/__init__.py +58 -0
- aipt_v2/evasion/request_obfuscator.py +272 -0
- aipt_v2/evasion/tls_fingerprint.py +285 -0
- aipt_v2/evasion/ua_rotator.py +301 -0
- aipt_v2/evasion/waf_bypass.py +439 -0
- aipt_v2/execution/__init__.py +23 -0
- aipt_v2/execution/executor.py +302 -0
- aipt_v2/execution/parser.py +544 -0
- aipt_v2/execution/terminal.py +337 -0
- aipt_v2/health.py +437 -0
- aipt_v2/intelligence/__init__.py +194 -0
- aipt_v2/intelligence/adaptation.py +474 -0
- aipt_v2/intelligence/auth.py +520 -0
- aipt_v2/intelligence/chaining.py +775 -0
- aipt_v2/intelligence/correlation.py +536 -0
- aipt_v2/intelligence/cve_aipt.py +334 -0
- aipt_v2/intelligence/cve_info.py +1111 -0
- aipt_v2/intelligence/knowledge_graph.py +590 -0
- aipt_v2/intelligence/learning.py +626 -0
- aipt_v2/intelligence/llm_analyzer.py +502 -0
- aipt_v2/intelligence/llm_tool_selector.py +518 -0
- aipt_v2/intelligence/payload_generator.py +562 -0
- aipt_v2/intelligence/rag.py +239 -0
- aipt_v2/intelligence/scope.py +442 -0
- aipt_v2/intelligence/searchers/__init__.py +5 -0
- aipt_v2/intelligence/searchers/exploitdb_searcher.py +523 -0
- aipt_v2/intelligence/searchers/github_searcher.py +467 -0
- aipt_v2/intelligence/searchers/google_searcher.py +281 -0
- aipt_v2/intelligence/tools.json +443 -0
- aipt_v2/intelligence/triage.py +670 -0
- aipt_v2/interactive_shell.py +559 -0
- aipt_v2/interface/__init__.py +5 -0
- aipt_v2/interface/cli.py +230 -0
- aipt_v2/interface/main.py +501 -0
- aipt_v2/interface/tui.py +1276 -0
- aipt_v2/interface/utils.py +583 -0
- aipt_v2/llm/__init__.py +39 -0
- aipt_v2/llm/config.py +26 -0
- aipt_v2/llm/llm.py +514 -0
- aipt_v2/llm/memory.py +214 -0
- aipt_v2/llm/request_queue.py +89 -0
- aipt_v2/llm/utils.py +89 -0
- aipt_v2/local_tool_installer.py +1467 -0
- aipt_v2/models/__init__.py +15 -0
- aipt_v2/models/findings.py +295 -0
- aipt_v2/models/phase_result.py +224 -0
- aipt_v2/models/scan_config.py +207 -0
- aipt_v2/monitoring/grafana/dashboards/aipt-dashboard.json +355 -0
- aipt_v2/monitoring/grafana/dashboards/default.yml +17 -0
- aipt_v2/monitoring/grafana/datasources/prometheus.yml +17 -0
- aipt_v2/monitoring/prometheus.yml +60 -0
- aipt_v2/orchestration/__init__.py +52 -0
- aipt_v2/orchestration/pipeline.py +398 -0
- aipt_v2/orchestration/progress.py +300 -0
- aipt_v2/orchestration/scheduler.py +296 -0
- aipt_v2/orchestrator.py +2427 -0
- aipt_v2/payloads/__init__.py +27 -0
- aipt_v2/payloads/cmdi.py +150 -0
- aipt_v2/payloads/sqli.py +263 -0
- aipt_v2/payloads/ssrf.py +204 -0
- aipt_v2/payloads/templates.py +222 -0
- aipt_v2/payloads/traversal.py +166 -0
- aipt_v2/payloads/xss.py +204 -0
- aipt_v2/prompts/__init__.py +60 -0
- aipt_v2/proxy/__init__.py +29 -0
- aipt_v2/proxy/history.py +352 -0
- aipt_v2/proxy/interceptor.py +452 -0
- aipt_v2/recon/__init__.py +44 -0
- aipt_v2/recon/dns.py +241 -0
- aipt_v2/recon/osint.py +367 -0
- aipt_v2/recon/subdomain.py +372 -0
- aipt_v2/recon/tech_detect.py +311 -0
- aipt_v2/reports/__init__.py +17 -0
- aipt_v2/reports/generator.py +313 -0
- aipt_v2/reports/html_report.py +378 -0
- aipt_v2/runtime/__init__.py +53 -0
- aipt_v2/runtime/base.py +30 -0
- aipt_v2/runtime/docker.py +401 -0
- aipt_v2/runtime/local.py +346 -0
- aipt_v2/runtime/tool_server.py +205 -0
- aipt_v2/runtime/vps.py +830 -0
- aipt_v2/scanners/__init__.py +28 -0
- aipt_v2/scanners/base.py +273 -0
- aipt_v2/scanners/nikto.py +244 -0
- aipt_v2/scanners/nmap.py +402 -0
- aipt_v2/scanners/nuclei.py +273 -0
- aipt_v2/scanners/web.py +454 -0
- aipt_v2/scripts/security_audit.py +366 -0
- aipt_v2/setup_wizard.py +941 -0
- aipt_v2/skills/__init__.py +80 -0
- aipt_v2/skills/agents/__init__.py +14 -0
- aipt_v2/skills/agents/api_tester.py +706 -0
- aipt_v2/skills/agents/base.py +477 -0
- aipt_v2/skills/agents/code_review.py +459 -0
- aipt_v2/skills/agents/security_agent.py +336 -0
- aipt_v2/skills/agents/web_pentest.py +818 -0
- aipt_v2/skills/prompts/__init__.py +647 -0
- aipt_v2/system_detector.py +539 -0
- aipt_v2/telemetry/__init__.py +7 -0
- aipt_v2/telemetry/tracer.py +347 -0
- aipt_v2/terminal/__init__.py +28 -0
- aipt_v2/terminal/executor.py +400 -0
- aipt_v2/terminal/sandbox.py +350 -0
- aipt_v2/tools/__init__.py +44 -0
- aipt_v2/tools/active_directory/__init__.py +78 -0
- aipt_v2/tools/active_directory/ad_config.py +238 -0
- aipt_v2/tools/active_directory/bloodhound_wrapper.py +447 -0
- aipt_v2/tools/active_directory/kerberos_attacks.py +430 -0
- aipt_v2/tools/active_directory/ldap_enum.py +533 -0
- aipt_v2/tools/active_directory/smb_attacks.py +505 -0
- aipt_v2/tools/agents_graph/__init__.py +19 -0
- aipt_v2/tools/agents_graph/agents_graph_actions.py +69 -0
- aipt_v2/tools/api_security/__init__.py +76 -0
- aipt_v2/tools/api_security/api_discovery.py +608 -0
- aipt_v2/tools/api_security/graphql_scanner.py +622 -0
- aipt_v2/tools/api_security/jwt_analyzer.py +577 -0
- aipt_v2/tools/api_security/openapi_fuzzer.py +761 -0
- aipt_v2/tools/browser/__init__.py +5 -0
- aipt_v2/tools/browser/browser_actions.py +238 -0
- aipt_v2/tools/browser/browser_instance.py +535 -0
- aipt_v2/tools/browser/tab_manager.py +344 -0
- aipt_v2/tools/cloud/__init__.py +70 -0
- aipt_v2/tools/cloud/cloud_config.py +273 -0
- aipt_v2/tools/cloud/cloud_scanner.py +639 -0
- aipt_v2/tools/cloud/prowler_tool.py +571 -0
- aipt_v2/tools/cloud/scoutsuite_tool.py +359 -0
- aipt_v2/tools/executor.py +307 -0
- aipt_v2/tools/parser.py +408 -0
- aipt_v2/tools/proxy/__init__.py +5 -0
- aipt_v2/tools/proxy/proxy_actions.py +103 -0
- aipt_v2/tools/proxy/proxy_manager.py +789 -0
- aipt_v2/tools/registry.py +196 -0
- aipt_v2/tools/scanners/__init__.py +343 -0
- aipt_v2/tools/scanners/acunetix_tool.py +712 -0
- aipt_v2/tools/scanners/burp_tool.py +631 -0
- aipt_v2/tools/scanners/config.py +156 -0
- aipt_v2/tools/scanners/nessus_tool.py +588 -0
- aipt_v2/tools/scanners/zap_tool.py +612 -0
- aipt_v2/tools/terminal/__init__.py +5 -0
- aipt_v2/tools/terminal/terminal_actions.py +37 -0
- aipt_v2/tools/terminal/terminal_manager.py +153 -0
- aipt_v2/tools/terminal/terminal_session.py +449 -0
- aipt_v2/tools/tool_processing.py +108 -0
- aipt_v2/utils/__init__.py +17 -0
- aipt_v2/utils/logging.py +202 -0
- aipt_v2/utils/model_manager.py +187 -0
- aipt_v2/utils/searchers/__init__.py +269 -0
- aipt_v2/verify_install.py +793 -0
- aiptx-2.0.7.dist-info/METADATA +345 -0
- aiptx-2.0.7.dist-info/RECORD +187 -0
- aiptx-2.0.7.dist-info/WHEEL +5 -0
- aiptx-2.0.7.dist-info/entry_points.txt +7 -0
- aiptx-2.0.7.dist-info/licenses/LICENSE +21 -0
- aiptx-2.0.7.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,459 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Code Review Agent - AI-powered source code security review.
|
|
3
|
+
|
|
4
|
+
Performs comprehensive security analysis of source code to identify:
|
|
5
|
+
- Injection vulnerabilities (SQLi, XSS, Command Injection)
|
|
6
|
+
- Authentication/Authorization flaws
|
|
7
|
+
- Cryptographic issues
|
|
8
|
+
- Hardcoded secrets
|
|
9
|
+
- Insecure dependencies
|
|
10
|
+
- OWASP Top 10 vulnerabilities
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
import os
|
|
14
|
+
import re
|
|
15
|
+
from pathlib import Path
|
|
16
|
+
from typing import Any, Dict, List, Optional
|
|
17
|
+
|
|
18
|
+
import structlog
|
|
19
|
+
|
|
20
|
+
from aipt_v2.skills.agents.base import (
|
|
21
|
+
AgentConfig,
|
|
22
|
+
AgentResult,
|
|
23
|
+
BaseSecurityAgent,
|
|
24
|
+
Finding,
|
|
25
|
+
Severity,
|
|
26
|
+
VulnCategory,
|
|
27
|
+
register_tool,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
logger = structlog.get_logger()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
# Register code review tools
|
|
34
|
+
@register_tool(
|
|
35
|
+
name="read_file",
|
|
36
|
+
description="Read the contents of a source code file",
|
|
37
|
+
parameters={
|
|
38
|
+
"file_path": {"type": "string", "description": "Path to the file to read"}
|
|
39
|
+
},
|
|
40
|
+
category="code_review"
|
|
41
|
+
)
|
|
42
|
+
async def read_file(file_path: str) -> str:
|
|
43
|
+
"""Read a source code file."""
|
|
44
|
+
try:
|
|
45
|
+
path = Path(file_path)
|
|
46
|
+
if not path.exists():
|
|
47
|
+
return f"Error: File not found: {file_path}"
|
|
48
|
+
if not path.is_file():
|
|
49
|
+
return f"Error: Not a file: {file_path}"
|
|
50
|
+
|
|
51
|
+
# Limit file size to prevent memory issues
|
|
52
|
+
if path.stat().st_size > 1_000_000: # 1MB limit
|
|
53
|
+
return f"Error: File too large (>1MB): {file_path}"
|
|
54
|
+
|
|
55
|
+
content = path.read_text(encoding='utf-8', errors='replace')
|
|
56
|
+
return f"File: {file_path}\n\n{content}"
|
|
57
|
+
|
|
58
|
+
except Exception as e:
|
|
59
|
+
return f"Error reading file: {str(e)}"
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@register_tool(
|
|
63
|
+
name="list_files",
|
|
64
|
+
description="List files in a directory with optional filtering by extension",
|
|
65
|
+
parameters={
|
|
66
|
+
"directory": {"type": "string", "description": "Directory path to list"},
|
|
67
|
+
"extension": {"type": "string", "description": "Optional file extension filter (e.g., '.py', '.js')"}
|
|
68
|
+
},
|
|
69
|
+
category="code_review"
|
|
70
|
+
)
|
|
71
|
+
async def list_files(directory: str, extension: Optional[str] = None) -> str:
|
|
72
|
+
"""List files in a directory."""
|
|
73
|
+
try:
|
|
74
|
+
path = Path(directory)
|
|
75
|
+
if not path.exists():
|
|
76
|
+
return f"Error: Directory not found: {directory}"
|
|
77
|
+
if not path.is_dir():
|
|
78
|
+
return f"Error: Not a directory: {directory}"
|
|
79
|
+
|
|
80
|
+
files = []
|
|
81
|
+
for item in path.rglob("*"):
|
|
82
|
+
if item.is_file():
|
|
83
|
+
if extension is None or item.suffix == extension:
|
|
84
|
+
files.append(str(item.relative_to(path)))
|
|
85
|
+
|
|
86
|
+
if not files:
|
|
87
|
+
return f"No files found in {directory}" + (f" with extension {extension}" if extension else "")
|
|
88
|
+
|
|
89
|
+
return f"Files in {directory}:\n" + "\n".join(sorted(files)[:200]) # Limit to 200 files
|
|
90
|
+
|
|
91
|
+
except Exception as e:
|
|
92
|
+
return f"Error listing files: {str(e)}"
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
@register_tool(
|
|
96
|
+
name="search_code",
|
|
97
|
+
description="Search for a pattern in code files",
|
|
98
|
+
parameters={
|
|
99
|
+
"directory": {"type": "string", "description": "Directory to search in"},
|
|
100
|
+
"pattern": {"type": "string", "description": "Regex pattern to search for"},
|
|
101
|
+
"file_extension": {"type": "string", "description": "Optional file extension filter"}
|
|
102
|
+
},
|
|
103
|
+
category="code_review"
|
|
104
|
+
)
|
|
105
|
+
async def search_code(directory: str, pattern: str, file_extension: Optional[str] = None) -> str:
|
|
106
|
+
"""Search for a pattern in code files."""
|
|
107
|
+
try:
|
|
108
|
+
path = Path(directory)
|
|
109
|
+
if not path.exists():
|
|
110
|
+
return f"Error: Directory not found: {directory}"
|
|
111
|
+
|
|
112
|
+
regex = re.compile(pattern, re.IGNORECASE)
|
|
113
|
+
matches = []
|
|
114
|
+
|
|
115
|
+
for item in path.rglob("*"):
|
|
116
|
+
if not item.is_file():
|
|
117
|
+
continue
|
|
118
|
+
if file_extension and item.suffix != file_extension:
|
|
119
|
+
continue
|
|
120
|
+
|
|
121
|
+
try:
|
|
122
|
+
content = item.read_text(encoding='utf-8', errors='replace')
|
|
123
|
+
for i, line in enumerate(content.split('\n'), 1):
|
|
124
|
+
if regex.search(line):
|
|
125
|
+
matches.append(f"{item}:{i}: {line.strip()[:100]}")
|
|
126
|
+
|
|
127
|
+
if len(matches) >= 100: # Limit results
|
|
128
|
+
matches.append("... (truncated, more matches exist)")
|
|
129
|
+
return "\n".join(matches)
|
|
130
|
+
|
|
131
|
+
except Exception:
|
|
132
|
+
continue
|
|
133
|
+
|
|
134
|
+
if not matches:
|
|
135
|
+
return f"No matches found for pattern: {pattern}"
|
|
136
|
+
|
|
137
|
+
return f"Matches for '{pattern}':\n" + "\n".join(matches)
|
|
138
|
+
|
|
139
|
+
except Exception as e:
|
|
140
|
+
return f"Error searching: {str(e)}"
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
@register_tool(
|
|
144
|
+
name="analyze_dependencies",
|
|
145
|
+
description="Analyze project dependencies for known vulnerabilities",
|
|
146
|
+
parameters={
|
|
147
|
+
"directory": {"type": "string", "description": "Project directory"}
|
|
148
|
+
},
|
|
149
|
+
category="code_review"
|
|
150
|
+
)
|
|
151
|
+
async def analyze_dependencies(directory: str) -> str:
|
|
152
|
+
"""Analyze project dependencies."""
|
|
153
|
+
try:
|
|
154
|
+
path = Path(directory)
|
|
155
|
+
results = []
|
|
156
|
+
|
|
157
|
+
# Check for various dependency files
|
|
158
|
+
dep_files = {
|
|
159
|
+
"package.json": "Node.js",
|
|
160
|
+
"requirements.txt": "Python",
|
|
161
|
+
"Pipfile": "Python (Pipenv)",
|
|
162
|
+
"pyproject.toml": "Python (Poetry/PEP)",
|
|
163
|
+
"Gemfile": "Ruby",
|
|
164
|
+
"composer.json": "PHP",
|
|
165
|
+
"pom.xml": "Java (Maven)",
|
|
166
|
+
"build.gradle": "Java (Gradle)",
|
|
167
|
+
"go.mod": "Go",
|
|
168
|
+
"Cargo.toml": "Rust",
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
for dep_file, lang in dep_files.items():
|
|
172
|
+
dep_path = path / dep_file
|
|
173
|
+
if dep_path.exists():
|
|
174
|
+
content = dep_path.read_text(encoding='utf-8', errors='replace')
|
|
175
|
+
results.append(f"\n=== {dep_file} ({lang}) ===\n{content[:2000]}")
|
|
176
|
+
|
|
177
|
+
if not results:
|
|
178
|
+
return "No dependency files found in the project."
|
|
179
|
+
|
|
180
|
+
return "Dependency Analysis:\n" + "\n".join(results)
|
|
181
|
+
|
|
182
|
+
except Exception as e:
|
|
183
|
+
return f"Error analyzing dependencies: {str(e)}"
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
@register_tool(
|
|
187
|
+
name="report_finding",
|
|
188
|
+
description="Report a security vulnerability finding",
|
|
189
|
+
parameters={
|
|
190
|
+
"title": {"type": "string", "description": "Title of the vulnerability"},
|
|
191
|
+
"severity": {"type": "string", "description": "Severity: critical, high, medium, low, info"},
|
|
192
|
+
"category": {"type": "string", "description": "Vulnerability category"},
|
|
193
|
+
"description": {"type": "string", "description": "Detailed description"},
|
|
194
|
+
"evidence": {"type": "string", "description": "Code snippet or evidence"},
|
|
195
|
+
"location": {"type": "string", "description": "File path and line number"},
|
|
196
|
+
"remediation": {"type": "string", "description": "How to fix"},
|
|
197
|
+
"cwe_id": {"type": "string", "description": "CWE identifier (e.g., CWE-89)"}
|
|
198
|
+
},
|
|
199
|
+
category="code_review"
|
|
200
|
+
)
|
|
201
|
+
async def report_finding(
|
|
202
|
+
title: str,
|
|
203
|
+
severity: str,
|
|
204
|
+
category: str,
|
|
205
|
+
description: str,
|
|
206
|
+
evidence: str,
|
|
207
|
+
location: str,
|
|
208
|
+
remediation: str,
|
|
209
|
+
cwe_id: Optional[str] = None
|
|
210
|
+
) -> str:
|
|
211
|
+
"""Report a security finding."""
|
|
212
|
+
return f"""Finding Recorded:
|
|
213
|
+
Title: {title}
|
|
214
|
+
Severity: {severity}
|
|
215
|
+
Category: {category}
|
|
216
|
+
Location: {location}
|
|
217
|
+
CWE: {cwe_id or 'N/A'}
|
|
218
|
+
Description: {description}
|
|
219
|
+
Evidence: {evidence[:500]}
|
|
220
|
+
Remediation: {remediation}
|
|
221
|
+
"""
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
CODE_REVIEW_SYSTEM_PROMPT = """You are an expert security code reviewer with deep knowledge of:
|
|
225
|
+
- OWASP Top 10 vulnerabilities
|
|
226
|
+
- Language-specific security issues (Python, JavaScript, Java, Go, PHP, etc.)
|
|
227
|
+
- Secure coding practices
|
|
228
|
+
- Common vulnerability patterns
|
|
229
|
+
|
|
230
|
+
Your mission is to perform a comprehensive security review of the provided source code.
|
|
231
|
+
|
|
232
|
+
## REVIEW CHECKLIST
|
|
233
|
+
|
|
234
|
+
### Injection Vulnerabilities
|
|
235
|
+
- SQL Injection (raw queries, string concatenation)
|
|
236
|
+
- Command Injection (os.system, subprocess, exec)
|
|
237
|
+
- XSS (unescaped output, innerHTML)
|
|
238
|
+
- LDAP Injection
|
|
239
|
+
- XPath Injection
|
|
240
|
+
- Template Injection
|
|
241
|
+
|
|
242
|
+
### Authentication & Session
|
|
243
|
+
- Hardcoded credentials
|
|
244
|
+
- Weak password requirements
|
|
245
|
+
- Insecure session management
|
|
246
|
+
- Missing authentication
|
|
247
|
+
- Broken authentication logic
|
|
248
|
+
|
|
249
|
+
### Cryptography
|
|
250
|
+
- Weak algorithms (MD5, SHA1 for passwords, DES)
|
|
251
|
+
- Hardcoded keys/secrets
|
|
252
|
+
- Insecure random number generation
|
|
253
|
+
- Missing encryption for sensitive data
|
|
254
|
+
|
|
255
|
+
### Data Exposure
|
|
256
|
+
- Sensitive data in logs
|
|
257
|
+
- Exposed API keys/secrets
|
|
258
|
+
- PII handling issues
|
|
259
|
+
- Insufficient data protection
|
|
260
|
+
|
|
261
|
+
### Access Control
|
|
262
|
+
- Missing authorization checks
|
|
263
|
+
- IDOR vulnerabilities
|
|
264
|
+
- Path traversal
|
|
265
|
+
- Privilege escalation
|
|
266
|
+
|
|
267
|
+
### Configuration & Dependencies
|
|
268
|
+
- Debug mode in production
|
|
269
|
+
- Exposed sensitive endpoints
|
|
270
|
+
- Outdated/vulnerable dependencies
|
|
271
|
+
- Insecure defaults
|
|
272
|
+
|
|
273
|
+
## METHODOLOGY
|
|
274
|
+
|
|
275
|
+
1. First, understand the codebase structure using list_files
|
|
276
|
+
2. Identify the technology stack and frameworks
|
|
277
|
+
3. Search for common vulnerability patterns
|
|
278
|
+
4. Read and analyze suspicious files
|
|
279
|
+
5. Report each finding using report_finding
|
|
280
|
+
|
|
281
|
+
## OUTPUT
|
|
282
|
+
|
|
283
|
+
For each vulnerability found, use the report_finding tool with:
|
|
284
|
+
- Clear, specific title
|
|
285
|
+
- Accurate severity assessment
|
|
286
|
+
- Vulnerable code location with line numbers
|
|
287
|
+
- Evidence (the actual vulnerable code)
|
|
288
|
+
- Specific remediation steps
|
|
289
|
+
- CWE identifier when applicable
|
|
290
|
+
|
|
291
|
+
Be thorough and systematic. Check ALL files. Don't stop until you've reviewed the entire codebase or exhausted the step limit.
|
|
292
|
+
|
|
293
|
+
Severity Guidelines:
|
|
294
|
+
- CRITICAL: Remote code execution, authentication bypass, hardcoded admin credentials
|
|
295
|
+
- HIGH: SQL injection, XSS, SSRF, path traversal with file read
|
|
296
|
+
- MEDIUM: Information disclosure, weak cryptography, missing security headers
|
|
297
|
+
- LOW: Best practice violations, minor information leaks
|
|
298
|
+
- INFO: Observations and recommendations"""
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
class CodeReviewAgent(BaseSecurityAgent):
|
|
302
|
+
"""
|
|
303
|
+
AI-powered source code security reviewer.
|
|
304
|
+
|
|
305
|
+
Performs comprehensive security analysis including:
|
|
306
|
+
- Static analysis for vulnerability patterns
|
|
307
|
+
- Dependency checking
|
|
308
|
+
- Secret detection
|
|
309
|
+
- Configuration review
|
|
310
|
+
|
|
311
|
+
Usage:
|
|
312
|
+
agent = CodeReviewAgent(target_path="/path/to/code")
|
|
313
|
+
result = await agent.run()
|
|
314
|
+
for finding in result.findings:
|
|
315
|
+
print(f"{finding.severity}: {finding.title}")
|
|
316
|
+
"""
|
|
317
|
+
|
|
318
|
+
def __init__(
|
|
319
|
+
self,
|
|
320
|
+
target_path: str,
|
|
321
|
+
config: Optional[AgentConfig] = None,
|
|
322
|
+
focus_areas: Optional[List[str]] = None,
|
|
323
|
+
exclude_patterns: Optional[List[str]] = None
|
|
324
|
+
):
|
|
325
|
+
"""
|
|
326
|
+
Initialize the code review agent.
|
|
327
|
+
|
|
328
|
+
Args:
|
|
329
|
+
target_path: Path to the code directory to review
|
|
330
|
+
config: Agent configuration
|
|
331
|
+
focus_areas: Specific areas to focus on (e.g., ["authentication", "sql"])
|
|
332
|
+
exclude_patterns: File patterns to exclude (e.g., ["*.test.js", "node_modules/*"])
|
|
333
|
+
"""
|
|
334
|
+
super().__init__(config)
|
|
335
|
+
self.target_path = Path(target_path).resolve()
|
|
336
|
+
self.focus_areas = focus_areas or []
|
|
337
|
+
self.exclude_patterns = exclude_patterns or [
|
|
338
|
+
"node_modules/*", "venv/*", ".venv/*", "__pycache__/*",
|
|
339
|
+
"*.min.js", "*.bundle.js", "dist/*", "build/*"
|
|
340
|
+
]
|
|
341
|
+
|
|
342
|
+
if not self.target_path.exists():
|
|
343
|
+
raise ValueError(f"Target path does not exist: {target_path}")
|
|
344
|
+
|
|
345
|
+
def get_system_prompt(self) -> str:
|
|
346
|
+
"""Get the code review system prompt."""
|
|
347
|
+
prompt = CODE_REVIEW_SYSTEM_PROMPT
|
|
348
|
+
|
|
349
|
+
# Add focus areas if specified
|
|
350
|
+
if self.focus_areas:
|
|
351
|
+
prompt += f"\n\n## FOCUS AREAS\nPrioritize checking for: {', '.join(self.focus_areas)}"
|
|
352
|
+
|
|
353
|
+
return prompt
|
|
354
|
+
|
|
355
|
+
def get_tools(self) -> List[Dict[str, Any]]:
|
|
356
|
+
"""Get tools available for code review."""
|
|
357
|
+
return [
|
|
358
|
+
{
|
|
359
|
+
"name": "read_file",
|
|
360
|
+
"description": "Read the contents of a source code file",
|
|
361
|
+
"parameters": {
|
|
362
|
+
"file_path": {"type": "string", "description": "Path to the file to read"}
|
|
363
|
+
},
|
|
364
|
+
"required": ["file_path"]
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
"name": "list_files",
|
|
368
|
+
"description": "List files in a directory with optional filtering by extension",
|
|
369
|
+
"parameters": {
|
|
370
|
+
"directory": {"type": "string", "description": "Directory path to list"},
|
|
371
|
+
"extension": {"type": "string", "description": "Optional file extension filter"}
|
|
372
|
+
},
|
|
373
|
+
"required": ["directory"]
|
|
374
|
+
},
|
|
375
|
+
{
|
|
376
|
+
"name": "search_code",
|
|
377
|
+
"description": "Search for a regex pattern in code files",
|
|
378
|
+
"parameters": {
|
|
379
|
+
"directory": {"type": "string", "description": "Directory to search in"},
|
|
380
|
+
"pattern": {"type": "string", "description": "Regex pattern to search for"},
|
|
381
|
+
"file_extension": {"type": "string", "description": "Optional file extension filter"}
|
|
382
|
+
},
|
|
383
|
+
"required": ["directory", "pattern"]
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
"name": "analyze_dependencies",
|
|
387
|
+
"description": "Analyze project dependencies for known vulnerabilities",
|
|
388
|
+
"parameters": {
|
|
389
|
+
"directory": {"type": "string", "description": "Project directory"}
|
|
390
|
+
},
|
|
391
|
+
"required": ["directory"]
|
|
392
|
+
},
|
|
393
|
+
{
|
|
394
|
+
"name": "report_finding",
|
|
395
|
+
"description": "Report a security vulnerability finding",
|
|
396
|
+
"parameters": {
|
|
397
|
+
"title": {"type": "string", "description": "Title of the vulnerability"},
|
|
398
|
+
"severity": {"type": "string", "description": "Severity: critical, high, medium, low, info"},
|
|
399
|
+
"category": {"type": "string", "description": "Vulnerability category"},
|
|
400
|
+
"description": {"type": "string", "description": "Detailed description"},
|
|
401
|
+
"evidence": {"type": "string", "description": "Code snippet or evidence"},
|
|
402
|
+
"location": {"type": "string", "description": "File path and line number"},
|
|
403
|
+
"remediation": {"type": "string", "description": "How to fix"},
|
|
404
|
+
"cwe_id": {"type": "string", "description": "CWE identifier"}
|
|
405
|
+
},
|
|
406
|
+
"required": ["title", "severity", "category", "description", "evidence", "location", "remediation"]
|
|
407
|
+
}
|
|
408
|
+
]
|
|
409
|
+
|
|
410
|
+
async def run(self, initial_message: Optional[str] = None) -> AgentResult:
|
|
411
|
+
"""
|
|
412
|
+
Run the code review.
|
|
413
|
+
|
|
414
|
+
Args:
|
|
415
|
+
initial_message: Optional additional instructions
|
|
416
|
+
|
|
417
|
+
Returns:
|
|
418
|
+
AgentResult with all security findings
|
|
419
|
+
"""
|
|
420
|
+
# Build the initial message
|
|
421
|
+
message = f"""Perform a comprehensive security code review of: {self.target_path}
|
|
422
|
+
|
|
423
|
+
Start by listing the files to understand the project structure, then systematically review each file for security vulnerabilities. Focus on:
|
|
424
|
+
1. Critical security issues first
|
|
425
|
+
2. Common vulnerability patterns
|
|
426
|
+
3. Secure coding best practices
|
|
427
|
+
|
|
428
|
+
{initial_message or ''}
|
|
429
|
+
|
|
430
|
+
Begin the review now."""
|
|
431
|
+
|
|
432
|
+
return await super().run(message)
|
|
433
|
+
|
|
434
|
+
async def quick_scan(self) -> AgentResult:
|
|
435
|
+
"""
|
|
436
|
+
Perform a quick security scan focusing on high-priority patterns.
|
|
437
|
+
|
|
438
|
+
Returns:
|
|
439
|
+
AgentResult with findings from pattern-based scanning
|
|
440
|
+
"""
|
|
441
|
+
# Use a reduced step limit for quick scan
|
|
442
|
+
original_max_steps = self.config.max_steps
|
|
443
|
+
self.config.max_steps = min(30, original_max_steps)
|
|
444
|
+
|
|
445
|
+
try:
|
|
446
|
+
message = f"""Perform a QUICK security scan of: {self.target_path}
|
|
447
|
+
|
|
448
|
+
Focus on HIGH PRIORITY patterns only:
|
|
449
|
+
1. Search for hardcoded secrets (passwords, API keys, tokens)
|
|
450
|
+
2. Search for SQL query construction
|
|
451
|
+
3. Search for command execution functions
|
|
452
|
+
4. Check dependency files for outdated packages
|
|
453
|
+
|
|
454
|
+
Do not read every file - use search_code to find suspicious patterns quickly.
|
|
455
|
+
Limit to finding the most critical issues."""
|
|
456
|
+
|
|
457
|
+
return await super().run(message)
|
|
458
|
+
finally:
|
|
459
|
+
self.config.max_steps = original_max_steps
|