This commit is contained in:
Dang Zerong
2026-03-12 14:42:23 +08:00
parent 9ae55407fc
commit 027cf50759
8 changed files with 225 additions and 52 deletions

View File

@@ -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]
})