Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ termcolor = "1"
chrono = { version = "0.4", features = ["serde"] }
colored = "2"
prettytable = "0.10"
term_size = "0.3"

# Vulnerability checking dependencies
rustsec = "0.29"
Expand Down
30 changes: 15 additions & 15 deletions docs/cli-display-modes.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,43 +20,43 @@ sync-ctl analyze .
📊 PROJECT ANALYSIS DASHBOARD
═══════════════════════════════════════════════════════════════════════════════════════════════════

┌─ Architecture Overview ────────────────────────────────────────────────────────────────────────┐
┌─ Architecture Overview ────────────────────────────────────────────────────────────────────────
│ Type: Monorepo (3 projects) │
│ Pattern: Fullstack │
│ Full-stack app with frontend/backend separation │
└─────────────────────────────────────────────────────────────────────────────────────────────────┘

┌─ Technology Stack ─────────────────────────────────────────────────────────────────────────────┐
┌─ Technology Stack ─────────────────────────────────────────────────────────────────────────────
│ Languages: TypeScript │
│ Frameworks: Encore, Tanstack Start │
│ Databases: Drizzle ORM │
└─────────────────────────────────────────────────────────────────────────────────────────────────┘

┌─ Projects Matrix ──────────────────────────────────────────────────────────────────────────────┐
│ ┌─────────────────┬──────────────┬───────────┬─────────────────┬───────┬────────┬──────
│ │ Project │ Type │ Languages │ Main Tech │ Ports │ Docker │ Deps
│ ├─────────────────┼──────────────┼───────────┼─────────────────┼───────┼────────┼──────
│ │ ⚙️ backend │ Backend │ TypeScript│ Encore │ 4000 │ ✓ │ 32
│ │ 🏗️ devops-agent │ Infrastructure│ TypeScript│ - │ - │ ✗ │ 5 │
│ │ 🌐 frontend │ Frontend │ TypeScript│ Tanstack Start │ 3000 │ ✓ │ 123 │
│ └─────────────────┴──────────────┴───────────┴─────────────────┴───────┴────────┴──────┘
└────────────────────────────────────────────────────────────────────────────────────────────────

┌─ Docker Infrastructure ────────────────────────────────────────────────────────────────────────┐
│ ┌─────────────────┬──────────────┬───────────┬─────────────────┬───────┬────────┬──────────┐
│ │ Project │ Type │ Languages │ Main Tech │ Ports │ Docker │ Deps
│ ├─────────────────┼──────────────┼───────────┼─────────────────┼───────┼────────┼──────────┤
│ │ backend │ Backend │ TypeScript│ Encore │ 4000 │ ✓ │ 32
│ │ devops-agent │ Infrastructure │ TypeScript │ - │ - │ ✗ │ 5 │ │
│ │ frontend │ Frontend │ TypeScript│ Tanstack Start │ 3000 │ ✓ │ 123 │ │
│ └─────────────────┴──────────────┴───────────┴─────────────────┴───────┴────────┴──────────
└────────────────────────────────────────────────────────────────────────────────────────────────┘

┌─ Docker Infrastructure ────────────────────────────────────────────────────────────────────────
│ Dockerfiles: 2 │
│ Compose Files: 2 │
│ Total Services: 5 │
│ Orchestration Patterns: Microservices │
│ ─────────────────────────────────────────────────────────────────────────────────────────────
│ ────────────────────────────────────────────────────────────────────────────────────────────────
│ Service Connectivity: │
│ encore-postgres: 5431:5432 │
│ encore: 4000:8080 → encore-postgres │
│ intellitask-app: 3000:3000 │
└─────────────────────────────────────────────────────────────────────────────────────────────────┘

┌─ Analysis Metrics ─────────────────────────────────────────────────────────────────────────────┐
⏱️ Duration: 57ms 📁 Files: 294 🎯 Score: 87% 🔖 Version: 0.3.0 │
└────────────────────────────────────────────────────────────────────────────────────────────────
Duration: 57ms Files: 294 Score: 87% Version: 0.3.0
└────────────────────────────────────────────────────────────────────────────────────────────────┘

═══════════════════════════════════════════════════════════════════════════════════════════════════
```
Expand Down
123 changes: 123 additions & 0 deletions examples/enhanced_security.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
//! Example: Enhanced Security Analysis
//!
//! This example demonstrates the enhanced security analysis capabilities
//! including the new modular JavaScript/TypeScript security analyzer.

use std::path::Path;
use syncable_cli::analyzer::{analyze_project, SecurityAnalyzer};

fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();

// For this example, analyze the current directory or a provided path
let project_path = std::env::args()
.nth(1)
.map(|p| Path::new(&p).to_path_buf())
.unwrap_or_else(|| std::env::current_dir().unwrap());

println!("🔍 Analyzing project security for: {}", project_path.display());

// First, perform regular project analysis to detect languages
let analysis = analyze_project(&project_path)?;

println!("\n📋 Detected Languages:");
for lang in &analysis.languages {
println!(" • {} (confidence: {:.1}%)", lang.name, lang.confidence * 100.0);
}

println!("\n🔧 Detected Technologies:");
for tech in &analysis.technologies {
println!(" • {} v{} ({:?})",
tech.name,
tech.version.as_deref().unwrap_or("unknown"),
tech.category
);
}

// Check if this is a JavaScript/TypeScript project
let has_js = analysis.languages.iter()
.any(|lang| matches!(lang.name.as_str(), "JavaScript" | "TypeScript" | "JSX" | "TSX"));

if has_js {
println!("\n✅ JavaScript/TypeScript project detected! Using enhanced security analysis...");
} else {
println!("\n📄 Using general security analysis...");
}

// Run enhanced security analysis
println!("\n🛡️ Starting enhanced security analysis...");

let mut security_analyzer = SecurityAnalyzer::new()?;
let security_report = security_analyzer.analyze_security_enhanced(&analysis)?;

// Display results
println!("\n📊 Security Analysis Results:");
println!(" Overall Score: {:.1}/100", security_report.overall_score);
println!(" Risk Level: {:?}", security_report.risk_level);
println!(" Total Findings: {}", security_report.total_findings);

if security_report.total_findings > 0 {
println!("\n🚨 Security Findings:");

// Group findings by severity
for severity in [
syncable_cli::analyzer::security::core::SecuritySeverity::Critical,
syncable_cli::analyzer::security::core::SecuritySeverity::High,
syncable_cli::analyzer::security::core::SecuritySeverity::Medium,
syncable_cli::analyzer::security::core::SecuritySeverity::Low,
] {
let findings: Vec<_> = security_report.findings.iter()
.filter(|f| f.severity == severity)
.collect();

if !findings.is_empty() {
let severity_icon = match severity {
syncable_cli::analyzer::security::core::SecuritySeverity::Critical => "🔴",
syncable_cli::analyzer::security::core::SecuritySeverity::High => "🟠",
syncable_cli::analyzer::security::core::SecuritySeverity::Medium => "🟡",
syncable_cli::analyzer::security::core::SecuritySeverity::Low => "🔵",
_ => "⚪",
};

println!("\n{} {:?} Severity ({} findings):", severity_icon, severity, findings.len());

for finding in findings.iter().take(3) { // Show first 3 of each severity
println!(" 📍 {}", finding.title);
if let Some(ref file_path) = finding.file_path {
let relative_path = file_path.strip_prefix(&project_path)
.unwrap_or(file_path);
print!(" 📄 {}", relative_path.display());
if let Some(line) = finding.line_number {
print!(":{}", line);
}
println!();
}
println!(" 💡 {}", finding.description);

if !finding.remediation.is_empty() {
println!(" 🔧 Remediation: {}", finding.remediation[0]);
}
println!();
}

if findings.len() > 3 {
println!(" ... and {} more findings", findings.len() - 3);
}
}
}

// Show recommendations
if !security_report.recommendations.is_empty() {
println!("\n💡 Recommendations:");
for (i, recommendation) in security_report.recommendations.iter().enumerate() {
println!(" {}. {}", i + 1, recommendation);
}
}
} else {
println!("✅ No security issues detected!");
}

println!("\n✨ Enhanced security analysis complete!");

Ok(())
}
4 changes: 2 additions & 2 deletions src/analyzer/frameworks/go.rs
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,12 @@ fn get_go_technology_rules() -> Vec<TechnologyRule> {
// CLI FRAMEWORKS
TechnologyRule {
name: "Cobra".to_string(),
category: TechnologyCategory::Library(LibraryType::Utility),
category: TechnologyCategory::Library(LibraryType::CLI),
confidence: 0.85,
dependency_patterns: vec!["github.com/spf13/cobra".to_string(), "cobra".to_string()],
requires: vec![],
conflicts_with: vec![],
is_primary_indicator: false,
is_primary_indicator: true,
alternative_names: vec!["spf13/cobra".to_string()],
},

Expand Down
12 changes: 6 additions & 6 deletions src/analyzer/frameworks/rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -414,32 +414,32 @@ fn get_rust_technology_rules() -> Vec<TechnologyRule> {
// CLI FRAMEWORKS
TechnologyRule {
name: "clap".to_string(),
category: TechnologyCategory::Library(LibraryType::Utility),
category: TechnologyCategory::Library(LibraryType::CLI),
confidence: 0.85,
dependency_patterns: vec!["clap".to_string()],
requires: vec![],
conflicts_with: vec![],
is_primary_indicator: false,
is_primary_indicator: true,
alternative_names: vec![],
},
TechnologyRule {
name: "structopt".to_string(),
category: TechnologyCategory::Library(LibraryType::Utility),
category: TechnologyCategory::Library(LibraryType::CLI),
confidence: 0.85,
dependency_patterns: vec!["structopt".to_string()],
requires: vec![],
conflicts_with: vec![],
is_primary_indicator: false,
is_primary_indicator: true,
alternative_names: vec![],
},
TechnologyRule {
name: "argh".to_string(),
category: TechnologyCategory::Library(LibraryType::Utility),
category: TechnologyCategory::Library(LibraryType::CLI),
confidence: 0.85,
dependency_patterns: vec!["argh".to_string()],
requires: vec![],
conflicts_with: vec![],
is_primary_indicator: false,
is_primary_indicator: true,
alternative_names: vec![],
},

Expand Down
10 changes: 10 additions & 0 deletions src/analyzer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ pub mod language_detector;
pub mod project_context;
pub mod vulnerability_checker;
pub mod security_analyzer;
pub mod security;
pub mod tool_installer;
pub mod monorepo_detector;
pub mod docker_analyzer;
Expand All @@ -36,6 +37,13 @@ pub use security_analyzer::{
SecurityCategory, ComplianceStatus, SecurityAnalysisConfig
};

// Re-export new modular security analysis types
pub use security::{
ModularSecurityAnalyzer, JavaScriptSecurityAnalyzer,
SecretPatternManager
};
pub use security::config::SecurityConfigPreset;

// Re-export monorepo analysis types
pub use monorepo_detector::{
MonorepoDetectionConfig, analyze_monorepo, analyze_monorepo_with_config
Expand Down Expand Up @@ -102,6 +110,8 @@ pub enum LibraryType {
HttpClient,
/// Authentication (Auth0, Firebase Auth)
Authentication,
/// CLI frameworks (clap, structopt, argh)
CLI,
/// Other specific types
Other(String),
}
Expand Down
Loading