syncable_cli/analyzer/security/
mod.rs1use std::path::Path;
12use thiserror::Error;
13
14pub mod core;
15pub mod javascript;
16pub mod patterns;
17pub mod config;
18pub mod gitignore;
19
20pub use core::{SecurityAnalyzer, SecurityReport, SecurityFinding, SecuritySeverity, SecurityCategory};
21pub use javascript::JavaScriptSecurityAnalyzer;
22pub use patterns::SecretPatternManager;
23pub use config::SecurityAnalysisConfig;
24pub use gitignore::{GitIgnoreAnalyzer, GitIgnoreStatus, GitIgnoreRisk};
25
26pub struct ModularSecurityAnalyzer {
28 javascript_analyzer: JavaScriptSecurityAnalyzer,
29 }
33
34impl ModularSecurityAnalyzer {
35 pub fn new() -> Result<Self, SecurityError> {
36 Ok(Self {
37 javascript_analyzer: JavaScriptSecurityAnalyzer::new()?,
38 })
39 }
40
41 pub fn with_config(config: SecurityAnalysisConfig) -> Result<Self, SecurityError> {
42 Ok(Self {
43 javascript_analyzer: JavaScriptSecurityAnalyzer::with_config(config.clone())?,
44 })
45 }
46
47 pub fn analyze_project(&mut self, project_root: &Path, languages: &[crate::analyzer::DetectedLanguage]) -> Result<SecurityReport, SecurityError> {
49 let mut all_findings = Vec::new();
50
51 if languages.iter().any(|lang| matches!(lang.name.as_str(), "JavaScript" | "TypeScript" | "JSX" | "TSX")) {
53 let js_report = self.javascript_analyzer.analyze_project(project_root)?;
54 all_findings.extend(js_report.findings);
55 }
56
57 Ok(SecurityReport::from_findings(all_findings))
61 }
62}
63
64#[derive(Debug, Error)]
65pub enum SecurityError {
66 #[error("Security analysis failed: {0}")]
67 AnalysisFailed(String),
68
69 #[error("Pattern compilation error: {0}")]
70 PatternError(#[from] regex::Error),
71
72 #[error("IO error: {0}")]
73 Io(#[from] std::io::Error),
74
75 #[error("JavaScript security analysis error: {0}")]
76 JavaScriptError(String),
77}