add web
This commit is contained in:
@@ -21,7 +21,7 @@ class SecurityScanner(BaseScanner):
|
||||
# 扫描所有代码文件以发现安全问题
|
||||
self.extensions = ['.py', '.js', '.ts', '.jsx', '.tsx', '.java', '.go', '.rb', '.php']
|
||||
|
||||
def scan(self, repo_url: str, commit_id: Optional[str], branch: str) -> Dict[str, Any]:
|
||||
def scan(self, repo_url: str, commit_id: Optional[str], branch: str, changed_files: Optional[List[str]] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
执行安全扫描
|
||||
|
||||
@@ -29,6 +29,7 @@ class SecurityScanner(BaseScanner):
|
||||
repo_url: 仓库 URL
|
||||
commit_id: 提交 ID
|
||||
branch: 分支名
|
||||
changed_files: 可选的变更文件列表(来自 PR)
|
||||
|
||||
Returns:
|
||||
扫描结果
|
||||
@@ -53,8 +54,8 @@ class SecurityScanner(BaseScanner):
|
||||
# 克隆仓库
|
||||
clone_dir = self.clone_repo(repo_url, commit_id, branch)
|
||||
|
||||
# 获取所有支持的文件
|
||||
all_files = self.get_changed_files(clone_dir, self.extensions)
|
||||
# 获取所有支持的文件(只扫描变更的文件)
|
||||
all_files = self.get_changed_files(clone_dir, self.extensions, changed_files)
|
||||
result['files_scanned'] = len(all_files)
|
||||
|
||||
if not all_files:
|
||||
@@ -88,7 +89,7 @@ class SecurityScanner(BaseScanner):
|
||||
|
||||
return result
|
||||
|
||||
def _run_bandit(self, cwd: str, files: List[str]) -> Dict[str, Any]:
|
||||
def _run_bandit(self, clone_dir: str, files: List[str]) -> Dict[str, Any]:
|
||||
"""运行 Bandit 安全扫描"""
|
||||
result = {
|
||||
'tool': 'bandit',
|
||||
@@ -98,7 +99,7 @@ class SecurityScanner(BaseScanner):
|
||||
try:
|
||||
# 运行 bandit
|
||||
cmd = ['python', '-m', 'bandit', '-f', 'json'] + files
|
||||
output = self.run_command(cmd, cwd, timeout=120)
|
||||
output = self.run_command(cmd, clone_dir, timeout=120)
|
||||
|
||||
# 解析 JSON 输出
|
||||
if output.get('stdout'):
|
||||
@@ -107,6 +108,9 @@ class SecurityScanner(BaseScanner):
|
||||
results = data.get('results', [])
|
||||
|
||||
for issue in results:
|
||||
# 使用相对于 clone_dir 的路径
|
||||
full_path = issue.get('filename', '')
|
||||
rel_path = os.path.relpath(full_path, clone_dir) if full_path else ''
|
||||
# 映射严重级别
|
||||
severity = issue.get('issue_severity', 'LOW')
|
||||
result['issues'].append({
|
||||
@@ -115,7 +119,7 @@ class SecurityScanner(BaseScanner):
|
||||
'severity': severity,
|
||||
'confidence': issue.get('issue_confidence', 'LOW'),
|
||||
'message': issue.get('issue_text', ''),
|
||||
'file': os.path.basename(issue.get('filename', '')),
|
||||
'file': rel_path,
|
||||
'line': issue.get('line_number', 0),
|
||||
'code': issue.get('code', '')
|
||||
})
|
||||
@@ -127,7 +131,7 @@ class SecurityScanner(BaseScanner):
|
||||
|
||||
return result
|
||||
|
||||
def _scan_js_security(self, cwd: str, files: List[str]) -> Dict[str, Any]:
|
||||
def _scan_js_security(self, clone_dir: str, files: List[str]) -> Dict[str, Any]:
|
||||
"""简单的 JavaScript 安全扫描(基于模式匹配)"""
|
||||
result = {
|
||||
'tool': 'js-security',
|
||||
@@ -172,6 +176,8 @@ class SecurityScanner(BaseScanner):
|
||||
|
||||
for file_path in files:
|
||||
try:
|
||||
# 使用相对于 clone_dir 的路径
|
||||
rel_path = os.path.relpath(file_path, clone_dir) if file_path else ''
|
||||
with open(file_path, 'r', encoding='utf-8', errors='ignore') as f:
|
||||
content = f.read()
|
||||
lines = content.split('\n')
|
||||
@@ -185,7 +191,7 @@ class SecurityScanner(BaseScanner):
|
||||
'severity': pattern_info['severity'],
|
||||
'confidence': 'MEDIUM',
|
||||
'message': pattern_info['message'],
|
||||
'file': os.path.basename(file_path),
|
||||
'file': rel_path,
|
||||
'line': line_num,
|
||||
'code': line.strip()[:80]
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user