""" JavaScript代码分析器 """ import re import os from typing import List, Dict, Any from .base_analyzer import BaseAnalyzer class JavaScriptAnalyzer(BaseAnalyzer): """JavaScript代码分析器""" def __init__(self): super().__init__() self.name = "JavaScript Analyzer" self.version = "1.0.0" self.supported_extensions = ["js", "jsx", "ts", "tsx"] self.description = "JavaScript/TypeScript代码静态分析器" async def analyze(self, project_path: str, config: Dict[str, Any] = None) -> List[Dict[str, Any]]: """分析JavaScript代码""" vulnerabilities = [] # 获取所有JavaScript文件 js_files = self.get_project_files(project_path) for file_path in js_files: try: # 读取文件内容 content = self.read_file_content(file_path) if not content: continue lines = content.split('\n') # 执行各种检查 vulnerabilities.extend(self._check_security_issues(lines, file_path)) vulnerabilities.extend(self._check_performance_issues(lines, file_path)) vulnerabilities.extend(self._check_maintainability_issues(lines, file_path)) except Exception as e: # 分析错误 vulnerabilities.append(self.create_vulnerability( rule_id="JS000", message=f"分析错误: {str(e)}", file_path=file_path, severity="high", category="reliability" )) return vulnerabilities def _check_security_issues(self, lines: List[str], file_path: str) -> List[Dict[str, Any]]: """检查安全问题""" vulnerabilities = [] for i, line in enumerate(lines): line_num = i + 1 line_stripped = line.strip() # 检查eval使用 if 'eval(' in line_stripped: vulnerabilities.append(self.create_vulnerability( rule_id="JS101", message="使用eval(),存在代码注入风险", file_path=file_path, line_number=line_num, severity="critical", category="security", code_snippet=line_stripped )) # 检查innerHTML使用 elif 'innerHTML' in line_stripped and '=' in line_stripped: vulnerabilities.append(self.create_vulnerability( rule_id="JS102", message="使用innerHTML,存在XSS风险", file_path=file_path, line_number=line_num, severity="high", category="security", code_snippet=line_stripped )) # 检查document.write使用 elif 'document.write(' in line_stripped: vulnerabilities.append(self.create_vulnerability( rule_id="JS103", message="使用document.write(),存在XSS风险", file_path=file_path, line_number=line_num, severity="high", category="security", code_snippet=line_stripped )) # 检查console.log在生产环境中的使用 elif 'console.log(' in line_stripped: vulnerabilities.append(self.create_vulnerability( rule_id="JS104", message="生产环境中不应使用console.log", file_path=file_path, line_number=line_num, severity="low", category="security", code_snippet=line_stripped )) # 检查硬编码的敏感信息 elif re.search(r'password\s*[:=]\s*["\'][^"\']+["\']', line_stripped, re.IGNORECASE): vulnerabilities.append(self.create_vulnerability( rule_id="JS105", message="代码中包含硬编码的密码", file_path=file_path, line_number=line_num, severity="high", category="security", code_snippet=line_stripped )) return vulnerabilities def _check_performance_issues(self, lines: List[str], file_path: str) -> List[Dict[str, Any]]: """检查性能问题""" vulnerabilities = [] for i, line in enumerate(lines): line_num = i + 1 line_stripped = line.strip() # 检查DOM操作在循环中 if re.search(r'for\s*\([^)]*\)\s*\{', line_stripped): # 查找循环体中的DOM操作 for j in range(i + 1, min(i + 20, len(lines))): loop_line = lines[j].strip() if loop_line == '}': break if any(dom_op in loop_line for dom_op in ['getElementById', 'querySelector', 'appendChild']): vulnerabilities.append(self.create_vulnerability( rule_id="JS201", message="循环中进行DOM操作,影响性能", file_path=file_path, line_number=j + 1, severity="medium", category="performance", code_snippet=loop_line )) # 检查未使用的变量声明 elif line_stripped.startswith('var ') or line_stripped.startswith('let ') or line_stripped.startswith('const '): var_name = re.search(r'(var|let|const)\s+([a-zA-Z_$][a-zA-Z0-9_$]*)', line_stripped) if var_name: var_name = var_name.group(2) # 检查变量是否在后续代码中使用 is_used = False for k in range(i + 1, len(lines)): if var_name in lines[k]: is_used = True break if not is_used: vulnerabilities.append(self.create_vulnerability( rule_id="JS202", message=f"未使用的变量: {var_name}", file_path=file_path, line_number=line_num, severity="low", category="performance", code_snippet=line_stripped )) return vulnerabilities def _check_maintainability_issues(self, lines: List[str], file_path: str) -> List[Dict[str, Any]]: """检查可维护性问题""" vulnerabilities = [] for i, line in enumerate(lines): line_num = i + 1 line_stripped = line.strip() # 检查函数长度(简单检查) if line_stripped.startswith('function ') or re.match(r'const\s+\w+\s*=\s*\([^)]*\)\s*=>', line_stripped): # 计算函数体长度 brace_count = 0 function_start = i for j in range(i, len(lines)): line_content = lines[j] brace_count += line_content.count('{') brace_count -= line_content.count('}') if brace_count > 0 and j > i: continue elif brace_count == 0 and j > i: function_length = j - function_start if function_length > 30: vulnerabilities.append(self.create_vulnerability( rule_id="JS301", message="函数过长,建议拆分", file_path=file_path, line_number=line_num, severity="medium", category="maintainability", code_snippet=line_stripped )) break # 检查深度嵌套 elif line_stripped.endswith('{'): indent_level = len(line) - len(line.lstrip()) if indent_level > 40: # 假设每层缩进4个空格 vulnerabilities.append(self.create_vulnerability( rule_id="JS302", message="代码嵌套过深,影响可读性", file_path=file_path, line_number=line_num, severity="low", category="maintainability", code_snippet=line_stripped )) # 检查魔法数字 elif re.search(r'\b\d{3,}\b', line_stripped): vulnerabilities.append(self.create_vulnerability( rule_id="JS303", message="存在魔法数字,建议使用常量", file_path=file_path, line_number=line_num, severity="low", category="maintainability", code_snippet=line_stripped )) return vulnerabilities