empathy-framework 4.6.6__py3-none-any.whl ā 4.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- empathy_framework-4.7.1.dist-info/METADATA +690 -0
- empathy_framework-4.7.1.dist-info/RECORD +379 -0
- {empathy_framework-4.6.6.dist-info ā empathy_framework-4.7.1.dist-info}/top_level.txt +1 -2
- empathy_healthcare_plugin/monitors/monitoring/__init__.py +9 -9
- empathy_llm_toolkit/agent_factory/__init__.py +6 -6
- empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +7 -10
- empathy_llm_toolkit/agents_md/__init__.py +22 -0
- empathy_llm_toolkit/agents_md/loader.py +218 -0
- empathy_llm_toolkit/agents_md/parser.py +271 -0
- empathy_llm_toolkit/agents_md/registry.py +307 -0
- empathy_llm_toolkit/commands/__init__.py +51 -0
- empathy_llm_toolkit/commands/context.py +375 -0
- empathy_llm_toolkit/commands/loader.py +301 -0
- empathy_llm_toolkit/commands/models.py +231 -0
- empathy_llm_toolkit/commands/parser.py +371 -0
- empathy_llm_toolkit/commands/registry.py +429 -0
- empathy_llm_toolkit/config/__init__.py +8 -8
- empathy_llm_toolkit/config/unified.py +3 -7
- empathy_llm_toolkit/context/__init__.py +22 -0
- empathy_llm_toolkit/context/compaction.py +455 -0
- empathy_llm_toolkit/context/manager.py +434 -0
- empathy_llm_toolkit/hooks/__init__.py +24 -0
- empathy_llm_toolkit/hooks/config.py +306 -0
- empathy_llm_toolkit/hooks/executor.py +289 -0
- empathy_llm_toolkit/hooks/registry.py +302 -0
- empathy_llm_toolkit/hooks/scripts/__init__.py +39 -0
- empathy_llm_toolkit/hooks/scripts/evaluate_session.py +201 -0
- empathy_llm_toolkit/hooks/scripts/first_time_init.py +285 -0
- empathy_llm_toolkit/hooks/scripts/pre_compact.py +207 -0
- empathy_llm_toolkit/hooks/scripts/session_end.py +183 -0
- empathy_llm_toolkit/hooks/scripts/session_start.py +163 -0
- empathy_llm_toolkit/hooks/scripts/suggest_compact.py +225 -0
- empathy_llm_toolkit/learning/__init__.py +30 -0
- empathy_llm_toolkit/learning/evaluator.py +438 -0
- empathy_llm_toolkit/learning/extractor.py +514 -0
- empathy_llm_toolkit/learning/storage.py +560 -0
- empathy_llm_toolkit/providers.py +4 -11
- empathy_llm_toolkit/security/__init__.py +17 -17
- empathy_llm_toolkit/utils/tokens.py +2 -5
- empathy_os/__init__.py +202 -70
- empathy_os/cache_monitor.py +5 -3
- empathy_os/cli/__init__.py +11 -55
- empathy_os/cli/__main__.py +29 -15
- empathy_os/cli/commands/inspection.py +21 -12
- empathy_os/cli/commands/memory.py +4 -12
- empathy_os/cli/commands/profiling.py +198 -0
- empathy_os/cli/commands/utilities.py +27 -7
- empathy_os/cli.py +28 -57
- empathy_os/cli_unified.py +525 -1164
- empathy_os/cost_tracker.py +9 -3
- empathy_os/dashboard/server.py +200 -2
- empathy_os/hot_reload/__init__.py +7 -7
- empathy_os/hot_reload/config.py +6 -7
- empathy_os/hot_reload/integration.py +35 -35
- empathy_os/hot_reload/reloader.py +57 -57
- empathy_os/hot_reload/watcher.py +28 -28
- empathy_os/hot_reload/websocket.py +2 -2
- empathy_os/memory/__init__.py +11 -4
- empathy_os/memory/claude_memory.py +1 -1
- empathy_os/memory/cross_session.py +8 -12
- empathy_os/memory/edges.py +6 -6
- empathy_os/memory/file_session.py +770 -0
- empathy_os/memory/graph.py +30 -30
- empathy_os/memory/nodes.py +6 -6
- empathy_os/memory/short_term.py +15 -9
- empathy_os/memory/unified.py +606 -140
- empathy_os/meta_workflows/agent_creator.py +3 -9
- empathy_os/meta_workflows/cli_meta_workflows.py +113 -53
- empathy_os/meta_workflows/form_engine.py +6 -18
- empathy_os/meta_workflows/intent_detector.py +64 -24
- empathy_os/meta_workflows/models.py +3 -1
- empathy_os/meta_workflows/pattern_learner.py +13 -31
- empathy_os/meta_workflows/plan_generator.py +55 -47
- empathy_os/meta_workflows/session_context.py +2 -3
- empathy_os/meta_workflows/workflow.py +20 -51
- empathy_os/models/cli.py +2 -2
- empathy_os/models/tasks.py +1 -2
- empathy_os/models/telemetry.py +4 -1
- empathy_os/models/token_estimator.py +3 -1
- empathy_os/monitoring/alerts.py +938 -9
- empathy_os/monitoring/alerts_cli.py +346 -183
- empathy_os/orchestration/execution_strategies.py +12 -29
- empathy_os/orchestration/pattern_learner.py +20 -26
- empathy_os/orchestration/real_tools.py +6 -15
- empathy_os/platform_utils.py +2 -1
- empathy_os/plugins/__init__.py +2 -2
- empathy_os/plugins/base.py +64 -64
- empathy_os/plugins/registry.py +32 -32
- empathy_os/project_index/index.py +49 -15
- empathy_os/project_index/models.py +1 -2
- empathy_os/project_index/reports.py +1 -1
- empathy_os/project_index/scanner.py +1 -0
- empathy_os/redis_memory.py +10 -7
- empathy_os/resilience/__init__.py +1 -1
- empathy_os/resilience/health.py +10 -10
- empathy_os/routing/__init__.py +7 -7
- empathy_os/routing/chain_executor.py +37 -37
- empathy_os/routing/classifier.py +36 -36
- empathy_os/routing/smart_router.py +40 -40
- empathy_os/routing/{wizard_registry.py ā workflow_registry.py} +47 -47
- empathy_os/scaffolding/__init__.py +8 -8
- empathy_os/scaffolding/__main__.py +1 -1
- empathy_os/scaffolding/cli.py +28 -28
- empathy_os/socratic/__init__.py +3 -19
- empathy_os/socratic/ab_testing.py +25 -36
- empathy_os/socratic/blueprint.py +38 -38
- empathy_os/socratic/cli.py +34 -20
- empathy_os/socratic/collaboration.py +30 -28
- empathy_os/socratic/domain_templates.py +9 -1
- empathy_os/socratic/embeddings.py +17 -13
- empathy_os/socratic/engine.py +135 -70
- empathy_os/socratic/explainer.py +70 -60
- empathy_os/socratic/feedback.py +24 -19
- empathy_os/socratic/forms.py +15 -10
- empathy_os/socratic/generator.py +51 -35
- empathy_os/socratic/llm_analyzer.py +25 -23
- empathy_os/socratic/mcp_server.py +99 -159
- empathy_os/socratic/session.py +19 -13
- empathy_os/socratic/storage.py +98 -67
- empathy_os/socratic/success.py +38 -27
- empathy_os/socratic/visual_editor.py +51 -39
- empathy_os/socratic/web_ui.py +99 -66
- empathy_os/telemetry/cli.py +3 -1
- empathy_os/telemetry/usage_tracker.py +1 -3
- empathy_os/test_generator/__init__.py +3 -3
- empathy_os/test_generator/cli.py +28 -28
- empathy_os/test_generator/generator.py +64 -66
- empathy_os/test_generator/risk_analyzer.py +11 -11
- empathy_os/vscode_bridge 2.py +173 -0
- empathy_os/vscode_bridge.py +173 -0
- empathy_os/workflows/__init__.py +212 -120
- empathy_os/workflows/batch_processing.py +8 -24
- empathy_os/workflows/bug_predict.py +1 -1
- empathy_os/workflows/code_review.py +20 -5
- empathy_os/workflows/code_review_pipeline.py +13 -8
- empathy_os/workflows/keyboard_shortcuts/workflow.py +6 -2
- empathy_os/workflows/manage_documentation.py +1 -0
- empathy_os/workflows/orchestrated_health_check.py +6 -11
- empathy_os/workflows/orchestrated_release_prep.py +3 -3
- empathy_os/workflows/pr_review.py +18 -10
- empathy_os/workflows/progressive/README 2.md +454 -0
- empathy_os/workflows/progressive/__init__ 2.py +92 -0
- empathy_os/workflows/progressive/__init__.py +2 -12
- empathy_os/workflows/progressive/cli 2.py +242 -0
- empathy_os/workflows/progressive/cli.py +14 -37
- empathy_os/workflows/progressive/core 2.py +488 -0
- empathy_os/workflows/progressive/core.py +12 -12
- empathy_os/workflows/progressive/orchestrator 2.py +701 -0
- empathy_os/workflows/progressive/orchestrator.py +166 -144
- empathy_os/workflows/progressive/reports 2.py +528 -0
- empathy_os/workflows/progressive/reports.py +22 -31
- empathy_os/workflows/progressive/telemetry 2.py +280 -0
- empathy_os/workflows/progressive/telemetry.py +8 -14
- empathy_os/workflows/progressive/test_gen 2.py +514 -0
- empathy_os/workflows/progressive/test_gen.py +29 -48
- empathy_os/workflows/progressive/workflow 2.py +628 -0
- empathy_os/workflows/progressive/workflow.py +31 -70
- empathy_os/workflows/release_prep.py +21 -6
- empathy_os/workflows/release_prep_crew.py +1 -0
- empathy_os/workflows/secure_release.py +13 -6
- empathy_os/workflows/security_audit.py +8 -3
- empathy_os/workflows/test_coverage_boost_crew.py +3 -2
- empathy_os/workflows/test_maintenance_crew.py +1 -0
- empathy_os/workflows/test_runner.py +16 -12
- empathy_software_plugin/SOFTWARE_PLUGIN_README.md +25 -703
- empathy_software_plugin/cli.py +0 -122
- patterns/README.md +119 -0
- patterns/__init__.py +95 -0
- patterns/behavior.py +298 -0
- patterns/code_review_memory.json +441 -0
- patterns/core.py +97 -0
- patterns/debugging.json +3763 -0
- patterns/empathy.py +268 -0
- patterns/health_check_memory.json +505 -0
- patterns/input.py +161 -0
- patterns/memory_graph.json +8 -0
- patterns/refactoring_memory.json +1113 -0
- patterns/registry.py +663 -0
- patterns/security_memory.json +8 -0
- patterns/structural.py +415 -0
- patterns/validation.py +194 -0
- coach_wizards/__init__.py +0 -45
- coach_wizards/accessibility_wizard.py +0 -91
- coach_wizards/api_wizard.py +0 -91
- coach_wizards/base_wizard.py +0 -209
- coach_wizards/cicd_wizard.py +0 -91
- coach_wizards/code_reviewer_README.md +0 -60
- coach_wizards/code_reviewer_wizard.py +0 -180
- coach_wizards/compliance_wizard.py +0 -91
- coach_wizards/database_wizard.py +0 -91
- coach_wizards/debugging_wizard.py +0 -91
- coach_wizards/documentation_wizard.py +0 -91
- coach_wizards/generate_wizards.py +0 -347
- coach_wizards/localization_wizard.py +0 -173
- coach_wizards/migration_wizard.py +0 -91
- coach_wizards/monitoring_wizard.py +0 -91
- coach_wizards/observability_wizard.py +0 -91
- coach_wizards/performance_wizard.py +0 -91
- coach_wizards/prompt_engineering_wizard.py +0 -661
- coach_wizards/refactoring_wizard.py +0 -91
- coach_wizards/scaling_wizard.py +0 -90
- coach_wizards/security_wizard.py +0 -92
- coach_wizards/testing_wizard.py +0 -91
- empathy_framework-4.6.6.dist-info/METADATA +0 -1597
- empathy_framework-4.6.6.dist-info/RECORD +0 -410
- empathy_llm_toolkit/wizards/__init__.py +0 -43
- empathy_llm_toolkit/wizards/base_wizard.py +0 -364
- empathy_llm_toolkit/wizards/customer_support_wizard.py +0 -190
- empathy_llm_toolkit/wizards/healthcare_wizard.py +0 -378
- empathy_llm_toolkit/wizards/patient_assessment_README.md +0 -64
- empathy_llm_toolkit/wizards/patient_assessment_wizard.py +0 -193
- empathy_llm_toolkit/wizards/technology_wizard.py +0 -209
- empathy_os/wizard_factory_cli.py +0 -170
- empathy_software_plugin/wizards/__init__.py +0 -42
- empathy_software_plugin/wizards/advanced_debugging_wizard.py +0 -395
- empathy_software_plugin/wizards/agent_orchestration_wizard.py +0 -511
- empathy_software_plugin/wizards/ai_collaboration_wizard.py +0 -503
- empathy_software_plugin/wizards/ai_context_wizard.py +0 -441
- empathy_software_plugin/wizards/ai_documentation_wizard.py +0 -503
- empathy_software_plugin/wizards/base_wizard.py +0 -288
- empathy_software_plugin/wizards/book_chapter_wizard.py +0 -519
- empathy_software_plugin/wizards/code_review_wizard.py +0 -604
- empathy_software_plugin/wizards/debugging/__init__.py +0 -50
- empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +0 -414
- empathy_software_plugin/wizards/debugging/config_loaders.py +0 -446
- empathy_software_plugin/wizards/debugging/fix_applier.py +0 -469
- empathy_software_plugin/wizards/debugging/language_patterns.py +0 -385
- empathy_software_plugin/wizards/debugging/linter_parsers.py +0 -470
- empathy_software_plugin/wizards/debugging/verification.py +0 -369
- empathy_software_plugin/wizards/enhanced_testing_wizard.py +0 -537
- empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +0 -816
- empathy_software_plugin/wizards/multi_model_wizard.py +0 -501
- empathy_software_plugin/wizards/pattern_extraction_wizard.py +0 -422
- empathy_software_plugin/wizards/pattern_retriever_wizard.py +0 -400
- empathy_software_plugin/wizards/performance/__init__.py +0 -9
- empathy_software_plugin/wizards/performance/bottleneck_detector.py +0 -221
- empathy_software_plugin/wizards/performance/profiler_parsers.py +0 -278
- empathy_software_plugin/wizards/performance/trajectory_analyzer.py +0 -429
- empathy_software_plugin/wizards/performance_profiling_wizard.py +0 -305
- empathy_software_plugin/wizards/prompt_engineering_wizard.py +0 -425
- empathy_software_plugin/wizards/rag_pattern_wizard.py +0 -461
- empathy_software_plugin/wizards/security/__init__.py +0 -32
- empathy_software_plugin/wizards/security/exploit_analyzer.py +0 -290
- empathy_software_plugin/wizards/security/owasp_patterns.py +0 -241
- empathy_software_plugin/wizards/security/vulnerability_scanner.py +0 -604
- empathy_software_plugin/wizards/security_analysis_wizard.py +0 -322
- empathy_software_plugin/wizards/security_learning_wizard.py +0 -740
- empathy_software_plugin/wizards/tech_debt_wizard.py +0 -726
- empathy_software_plugin/wizards/testing/__init__.py +0 -27
- empathy_software_plugin/wizards/testing/coverage_analyzer.py +0 -459
- empathy_software_plugin/wizards/testing/quality_analyzer.py +0 -525
- empathy_software_plugin/wizards/testing/test_suggester.py +0 -533
- empathy_software_plugin/wizards/testing_wizard.py +0 -274
- wizards/__init__.py +0 -82
- wizards/admission_assessment_wizard.py +0 -644
- wizards/care_plan.py +0 -321
- wizards/clinical_assessment.py +0 -769
- wizards/discharge_planning.py +0 -77
- wizards/discharge_summary_wizard.py +0 -468
- wizards/dosage_calculation.py +0 -497
- wizards/incident_report_wizard.py +0 -454
- wizards/medication_reconciliation.py +0 -85
- wizards/nursing_assessment.py +0 -171
- wizards/patient_education.py +0 -654
- wizards/quality_improvement.py +0 -705
- wizards/sbar_report.py +0 -324
- wizards/sbar_wizard.py +0 -608
- wizards/shift_handoff_wizard.py +0 -535
- wizards/soap_note_wizard.py +0 -679
- wizards/treatment_plan.py +0 -15
- {empathy_framework-4.6.6.dist-info ā empathy_framework-4.7.1.dist-info}/WHEEL +0 -0
- {empathy_framework-4.6.6.dist-info ā empathy_framework-4.7.1.dist-info}/entry_points.txt +0 -0
- {empathy_framework-4.6.6.dist-info ā empathy_framework-4.7.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,604 +0,0 @@
|
|
|
1
|
-
"""Vulnerability Scanner for Security Analysis Wizard
|
|
2
|
-
|
|
3
|
-
Comprehensive vulnerability detection including:
|
|
4
|
-
- Dependency vulnerabilities (CVE matching)
|
|
5
|
-
- Secret detection (API keys, passwords, tokens)
|
|
6
|
-
- Configuration security issues
|
|
7
|
-
- OWASP Top 10 patterns
|
|
8
|
-
- Code security anti-patterns
|
|
9
|
-
|
|
10
|
-
Copyright 2025 Smart-AI-Memory
|
|
11
|
-
Licensed under Fair Source License 0.9
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
import json
|
|
15
|
-
import re
|
|
16
|
-
import subprocess
|
|
17
|
-
from dataclasses import dataclass
|
|
18
|
-
from enum import Enum
|
|
19
|
-
from pathlib import Path
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class VulnerabilityType(Enum):
|
|
23
|
-
"""Types of security vulnerabilities"""
|
|
24
|
-
|
|
25
|
-
SQL_INJECTION = "sql_injection"
|
|
26
|
-
XSS = "xss"
|
|
27
|
-
COMMAND_INJECTION = "command_injection"
|
|
28
|
-
PATH_TRAVERSAL = "path_traversal"
|
|
29
|
-
HARDCODED_SECRET = "hardcoded_secret"
|
|
30
|
-
WEAK_CRYPTO = "weak_crypto"
|
|
31
|
-
INSECURE_DESERIALIZATION = "insecure_deserialization"
|
|
32
|
-
XXE = "xxe" # XML External Entity
|
|
33
|
-
CSRF = "csrf"
|
|
34
|
-
SSRF = "ssrf" # Server-Side Request Forgery
|
|
35
|
-
DEPENDENCY_VULN = "dependency_vulnerability"
|
|
36
|
-
INSECURE_CONFIG = "insecure_configuration"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class Severity(Enum):
|
|
40
|
-
"""CVSS-based severity levels"""
|
|
41
|
-
|
|
42
|
-
CRITICAL = "critical" # CVSS 9.0-10.0
|
|
43
|
-
HIGH = "high" # CVSS 7.0-8.9
|
|
44
|
-
MEDIUM = "medium" # CVSS 4.0-6.9
|
|
45
|
-
LOW = "low" # CVSS 0.1-3.9
|
|
46
|
-
INFO = "info" # Informational
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
@dataclass
|
|
50
|
-
class Vulnerability:
|
|
51
|
-
"""Represents a detected security vulnerability"""
|
|
52
|
-
|
|
53
|
-
vuln_type: VulnerabilityType
|
|
54
|
-
severity: Severity
|
|
55
|
-
file_path: str
|
|
56
|
-
line_number: int
|
|
57
|
-
description: str
|
|
58
|
-
evidence: str # Code snippet or pattern matched
|
|
59
|
-
cwe_id: str | None = None # Common Weakness Enumeration
|
|
60
|
-
cve_id: str | None = None # Common Vulnerabilities and Exposures
|
|
61
|
-
cvss_score: float | None = None
|
|
62
|
-
remediation: str | None = None
|
|
63
|
-
references: list[str] | None = None
|
|
64
|
-
|
|
65
|
-
def __post_init__(self):
|
|
66
|
-
if self.references is None:
|
|
67
|
-
self.references = []
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
@dataclass
|
|
71
|
-
class DependencyVulnerability:
|
|
72
|
-
"""Vulnerability in a dependency package"""
|
|
73
|
-
|
|
74
|
-
package_name: str
|
|
75
|
-
installed_version: str
|
|
76
|
-
vulnerable_versions: str
|
|
77
|
-
fixed_version: str | None
|
|
78
|
-
cve_id: str
|
|
79
|
-
cvss_score: float
|
|
80
|
-
severity: Severity
|
|
81
|
-
description: str
|
|
82
|
-
references: list[str]
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
@dataclass
|
|
86
|
-
class VulnerabilityScanReport:
|
|
87
|
-
"""Complete vulnerability scan report"""
|
|
88
|
-
|
|
89
|
-
total_issues: int
|
|
90
|
-
critical_count: int
|
|
91
|
-
high_count: int
|
|
92
|
-
medium_count: int
|
|
93
|
-
low_count: int
|
|
94
|
-
info_count: int
|
|
95
|
-
vulnerabilities: list[Vulnerability]
|
|
96
|
-
dependency_vulnerabilities: list[DependencyVulnerability]
|
|
97
|
-
files_scanned: int
|
|
98
|
-
scan_duration: float # seconds
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
class VulnerabilityScanner:
|
|
102
|
-
"""Comprehensive vulnerability scanner for Python projects.
|
|
103
|
-
|
|
104
|
-
Detects:
|
|
105
|
-
- OWASP Top 10 vulnerabilities
|
|
106
|
-
- Hardcoded secrets
|
|
107
|
-
- Insecure dependencies
|
|
108
|
-
- Configuration issues
|
|
109
|
-
- Common security anti-patterns
|
|
110
|
-
"""
|
|
111
|
-
|
|
112
|
-
def __init__(self):
|
|
113
|
-
self._init_secret_patterns()
|
|
114
|
-
self._init_injection_patterns()
|
|
115
|
-
self._init_crypto_patterns()
|
|
116
|
-
|
|
117
|
-
def _init_secret_patterns(self):
|
|
118
|
-
"""Initialize patterns for secret detection"""
|
|
119
|
-
self.secret_patterns = {
|
|
120
|
-
"AWS Access Key": re.compile(r"AKIA[0-9A-Z]{16}"),
|
|
121
|
-
"AWS Secret Key": re.compile(
|
|
122
|
-
r'aws_secret_access_key\s*=\s*["\']([^"\']+)["\']',
|
|
123
|
-
re.IGNORECASE,
|
|
124
|
-
),
|
|
125
|
-
"API Key": re.compile(
|
|
126
|
-
r'api[_-]?key\s*[=:]\s*["\']([a-zA-Z0-9_\-]{20,})["\']',
|
|
127
|
-
re.IGNORECASE,
|
|
128
|
-
),
|
|
129
|
-
"Private Key": re.compile(r"-----BEGIN (RSA |EC |DSA )?PRIVATE KEY-----"),
|
|
130
|
-
"GitHub Token": re.compile(r"ghp_[a-zA-Z0-9]{36}"),
|
|
131
|
-
"Generic Secret": re.compile(
|
|
132
|
-
r'(secret|password|passwd|pwd)\s*[=:]\s*["\']([^"\']{8,})["\']',
|
|
133
|
-
re.IGNORECASE,
|
|
134
|
-
),
|
|
135
|
-
"JWT Token": re.compile(r"eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*"),
|
|
136
|
-
"Database URL": re.compile(r"(mysql|postgresql|mongodb)://[^:]+:[^@]+@", re.IGNORECASE),
|
|
137
|
-
"Slack Token": re.compile(r"xox[baprs]-[0-9a-zA-Z]{10,48}"),
|
|
138
|
-
"Stripe Key": re.compile(r"sk_live_[0-9a-zA-Z]{24}"),
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
def _init_injection_patterns(self):
|
|
142
|
-
"""Initialize patterns for injection vulnerabilities"""
|
|
143
|
-
self.injection_patterns = {
|
|
144
|
-
VulnerabilityType.SQL_INJECTION: [
|
|
145
|
-
(re.compile(r'execute\(["\'].*%s.*["\']'), "String formatting in SQL"),
|
|
146
|
-
(re.compile(r'execute\(["\'].*\+.*["\']'), "String concatenation in SQL"),
|
|
147
|
-
(re.compile(r'execute\(f["\'].*\{.*\}.*["\']'), "f-string in SQL"),
|
|
148
|
-
(re.compile(r"raw_sql\s*=.*\+"), "SQL string concatenation"),
|
|
149
|
-
],
|
|
150
|
-
VulnerabilityType.COMMAND_INJECTION: [
|
|
151
|
-
(re.compile(r"os\.system\(.*\+"), "os.system with concatenation"),
|
|
152
|
-
(
|
|
153
|
-
re.compile(r"subprocess\.(call|run|Popen)\(.*shell\s*=\s*True"),
|
|
154
|
-
"subprocess with shell=True",
|
|
155
|
-
),
|
|
156
|
-
(re.compile(r"eval\("), "Use of eval()"),
|
|
157
|
-
(re.compile(r"exec\("), "Use of exec()"),
|
|
158
|
-
],
|
|
159
|
-
VulnerabilityType.PATH_TRAVERSAL: [
|
|
160
|
-
(re.compile(r'open\(["\'].*\+'), "Path concatenation in file open"),
|
|
161
|
-
(re.compile(r"open\(.*\.format\("), "String formatting in file path"),
|
|
162
|
-
(re.compile(r"Path\(.*\+"), "Path concatenation"),
|
|
163
|
-
],
|
|
164
|
-
VulnerabilityType.XSS: [
|
|
165
|
-
(re.compile(r"\.innerHTML\s*="), "Direct innerHTML assignment"),
|
|
166
|
-
(re.compile(r"document\.write\("), "document.write usage"),
|
|
167
|
-
(re.compile(r"render_template_string\(.*\+"), "Unsafe template rendering"),
|
|
168
|
-
],
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
def _init_crypto_patterns(self):
|
|
172
|
-
"""Initialize patterns for cryptographic issues"""
|
|
173
|
-
self.crypto_patterns = {
|
|
174
|
-
"Weak Hash (MD5)": re.compile(r"hashlib\.md5\("),
|
|
175
|
-
"Weak Hash (SHA1)": re.compile(r"hashlib\.sha1\("),
|
|
176
|
-
"Weak Cipher (DES)": re.compile(r"Crypto\.Cipher\.(DES|DES3)"),
|
|
177
|
-
"Weak Cipher (RC4)": re.compile(r"Crypto\.Cipher\.ARC4"),
|
|
178
|
-
"Hardcoded IV": re.compile(r'iv\s*=\s*b?["\'][^"\']+["\']'),
|
|
179
|
-
"Random without seed": re.compile(r"random\.random\(\)"),
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
def scan_file(self, file_path: Path) -> list[Vulnerability]:
|
|
183
|
-
"""Scan a single file for vulnerabilities
|
|
184
|
-
|
|
185
|
-
Args:
|
|
186
|
-
file_path: Path to file to scan
|
|
187
|
-
|
|
188
|
-
Returns:
|
|
189
|
-
List of Vulnerability objects found
|
|
190
|
-
|
|
191
|
-
Raises:
|
|
192
|
-
FileNotFoundError: If file doesn't exist
|
|
193
|
-
|
|
194
|
-
"""
|
|
195
|
-
if not file_path.exists():
|
|
196
|
-
raise FileNotFoundError(f"File not found: {file_path}")
|
|
197
|
-
|
|
198
|
-
vulnerabilities = []
|
|
199
|
-
|
|
200
|
-
with open(file_path, encoding="utf-8", errors="ignore") as f:
|
|
201
|
-
content = f.read()
|
|
202
|
-
lines = content.split("\n")
|
|
203
|
-
|
|
204
|
-
# Scan for secrets
|
|
205
|
-
vulnerabilities.extend(self._scan_for_secrets(file_path, content, lines))
|
|
206
|
-
|
|
207
|
-
# Scan for injection vulnerabilities
|
|
208
|
-
vulnerabilities.extend(self._scan_for_injections(file_path, content, lines))
|
|
209
|
-
|
|
210
|
-
# Scan for crypto issues
|
|
211
|
-
vulnerabilities.extend(self._scan_for_crypto_issues(file_path, content, lines))
|
|
212
|
-
|
|
213
|
-
# Scan for insecure deserialization
|
|
214
|
-
vulnerabilities.extend(self._scan_for_deserialization(file_path, content, lines))
|
|
215
|
-
|
|
216
|
-
# Scan for CSRF issues (web frameworks)
|
|
217
|
-
vulnerabilities.extend(self._scan_for_csrf(file_path, content, lines))
|
|
218
|
-
|
|
219
|
-
return vulnerabilities
|
|
220
|
-
|
|
221
|
-
def _scan_for_secrets(
|
|
222
|
-
self,
|
|
223
|
-
file_path: Path,
|
|
224
|
-
content: str,
|
|
225
|
-
lines: list[str],
|
|
226
|
-
) -> list[Vulnerability]:
|
|
227
|
-
"""Scan for hardcoded secrets"""
|
|
228
|
-
vulnerabilities: list[Vulnerability] = []
|
|
229
|
-
|
|
230
|
-
# Skip certain file types
|
|
231
|
-
if file_path.suffix in [".md", ".txt", ".json", ".xml"]:
|
|
232
|
-
return vulnerabilities
|
|
233
|
-
|
|
234
|
-
for secret_type, pattern in self.secret_patterns.items():
|
|
235
|
-
for match in pattern.finditer(content):
|
|
236
|
-
# Find line number
|
|
237
|
-
line_num = content[: match.start()].count("\n") + 1
|
|
238
|
-
|
|
239
|
-
# Extract evidence (mask the actual secret)
|
|
240
|
-
evidence = lines[line_num - 1] if line_num <= len(lines) else ""
|
|
241
|
-
masked_evidence = self._mask_secret(evidence)
|
|
242
|
-
|
|
243
|
-
# Determine severity
|
|
244
|
-
if "private key" in secret_type.lower():
|
|
245
|
-
severity = Severity.CRITICAL
|
|
246
|
-
elif "password" in secret_type.lower():
|
|
247
|
-
severity = Severity.HIGH
|
|
248
|
-
else:
|
|
249
|
-
severity = Severity.MEDIUM
|
|
250
|
-
|
|
251
|
-
vuln = Vulnerability(
|
|
252
|
-
vuln_type=VulnerabilityType.HARDCODED_SECRET,
|
|
253
|
-
severity=severity,
|
|
254
|
-
file_path=str(file_path),
|
|
255
|
-
line_number=line_num,
|
|
256
|
-
description=f"Hardcoded {secret_type} detected",
|
|
257
|
-
evidence=masked_evidence,
|
|
258
|
-
cwe_id="CWE-798", # Use of Hard-coded Credentials
|
|
259
|
-
remediation="Use environment variables or secure secret management (e.g., AWS Secrets Manager, HashiCorp Vault)",
|
|
260
|
-
references=["https://cwe.mitre.org/data/definitions/798.html"],
|
|
261
|
-
)
|
|
262
|
-
vulnerabilities.append(vuln)
|
|
263
|
-
|
|
264
|
-
return vulnerabilities
|
|
265
|
-
|
|
266
|
-
def _scan_for_injections(
|
|
267
|
-
self,
|
|
268
|
-
file_path: Path,
|
|
269
|
-
content: str,
|
|
270
|
-
lines: list[str],
|
|
271
|
-
) -> list[Vulnerability]:
|
|
272
|
-
"""Scan for injection vulnerabilities"""
|
|
273
|
-
vulnerabilities = []
|
|
274
|
-
|
|
275
|
-
for vuln_type, patterns in self.injection_patterns.items():
|
|
276
|
-
for pattern, description in patterns:
|
|
277
|
-
for match in pattern.finditer(content):
|
|
278
|
-
line_num = content[: match.start()].count("\n") + 1
|
|
279
|
-
evidence = lines[line_num - 1] if line_num <= len(lines) else ""
|
|
280
|
-
|
|
281
|
-
# Determine severity and CWE
|
|
282
|
-
if vuln_type == VulnerabilityType.SQL_INJECTION:
|
|
283
|
-
severity = Severity.CRITICAL
|
|
284
|
-
cwe_id = "CWE-89"
|
|
285
|
-
remediation = "Use parameterized queries or an ORM with automatic escaping"
|
|
286
|
-
elif vuln_type == VulnerabilityType.COMMAND_INJECTION:
|
|
287
|
-
severity = Severity.CRITICAL
|
|
288
|
-
cwe_id = "CWE-78"
|
|
289
|
-
remediation = "Avoid shell=True, use list arguments, validate input"
|
|
290
|
-
elif vuln_type == VulnerabilityType.XSS:
|
|
291
|
-
severity = Severity.HIGH
|
|
292
|
-
cwe_id = "CWE-79"
|
|
293
|
-
remediation = (
|
|
294
|
-
"Use proper output encoding, template engines with auto-escaping"
|
|
295
|
-
)
|
|
296
|
-
else:
|
|
297
|
-
severity = Severity.HIGH
|
|
298
|
-
cwe_id = "CWE-20"
|
|
299
|
-
remediation = "Validate and sanitize all user input"
|
|
300
|
-
|
|
301
|
-
vuln = Vulnerability(
|
|
302
|
-
vuln_type=vuln_type,
|
|
303
|
-
severity=severity,
|
|
304
|
-
file_path=str(file_path),
|
|
305
|
-
line_number=line_num,
|
|
306
|
-
description=description,
|
|
307
|
-
evidence=evidence.strip(),
|
|
308
|
-
cwe_id=cwe_id,
|
|
309
|
-
remediation=remediation,
|
|
310
|
-
references=[
|
|
311
|
-
f"https://cwe.mitre.org/data/definitions/{cwe_id.split('-')[1]}.html",
|
|
312
|
-
],
|
|
313
|
-
)
|
|
314
|
-
vulnerabilities.append(vuln)
|
|
315
|
-
|
|
316
|
-
return vulnerabilities
|
|
317
|
-
|
|
318
|
-
def _scan_for_crypto_issues(
|
|
319
|
-
self,
|
|
320
|
-
file_path: Path,
|
|
321
|
-
content: str,
|
|
322
|
-
lines: list[str],
|
|
323
|
-
) -> list[Vulnerability]:
|
|
324
|
-
"""Scan for cryptographic issues"""
|
|
325
|
-
vulnerabilities = []
|
|
326
|
-
|
|
327
|
-
for issue_type, pattern in self.crypto_patterns.items():
|
|
328
|
-
for match in pattern.finditer(content):
|
|
329
|
-
line_num = content[: match.start()].count("\n") + 1
|
|
330
|
-
evidence = lines[line_num - 1] if line_num <= len(lines) else ""
|
|
331
|
-
|
|
332
|
-
vuln = Vulnerability(
|
|
333
|
-
vuln_type=VulnerabilityType.WEAK_CRYPTO,
|
|
334
|
-
severity=Severity.MEDIUM,
|
|
335
|
-
file_path=str(file_path),
|
|
336
|
-
line_number=line_num,
|
|
337
|
-
description=f"Weak cryptography: {issue_type}",
|
|
338
|
-
evidence=evidence.strip(),
|
|
339
|
-
cwe_id="CWE-327", # Use of Broken or Risky Cryptographic Algorithm
|
|
340
|
-
remediation="Use SHA-256 or better for hashing, AES for encryption",
|
|
341
|
-
references=["https://cwe.mitre.org/data/definitions/327.html"],
|
|
342
|
-
)
|
|
343
|
-
vulnerabilities.append(vuln)
|
|
344
|
-
|
|
345
|
-
return vulnerabilities
|
|
346
|
-
|
|
347
|
-
def _scan_for_deserialization(
|
|
348
|
-
self,
|
|
349
|
-
file_path: Path,
|
|
350
|
-
content: str,
|
|
351
|
-
lines: list[str],
|
|
352
|
-
) -> list[Vulnerability]:
|
|
353
|
-
"""Scan for insecure deserialization"""
|
|
354
|
-
vulnerabilities = []
|
|
355
|
-
|
|
356
|
-
# Patterns for unsafe deserialization
|
|
357
|
-
patterns = [
|
|
358
|
-
(
|
|
359
|
-
re.compile(r"pickle\.loads?\("),
|
|
360
|
-
"Use of pickle.load() - vulnerable to code execution",
|
|
361
|
-
),
|
|
362
|
-
(
|
|
363
|
-
re.compile(r"yaml\.load\((?!.*Loader=yaml\.SafeLoader)"),
|
|
364
|
-
"Use of yaml.load() without SafeLoader",
|
|
365
|
-
),
|
|
366
|
-
(re.compile(r"eval\("), "Use of eval() - code execution risk"),
|
|
367
|
-
]
|
|
368
|
-
|
|
369
|
-
for pattern, description in patterns:
|
|
370
|
-
for match in pattern.finditer(content):
|
|
371
|
-
line_num = content[: match.start()].count("\n") + 1
|
|
372
|
-
evidence = lines[line_num - 1] if line_num <= len(lines) else ""
|
|
373
|
-
|
|
374
|
-
vuln = Vulnerability(
|
|
375
|
-
vuln_type=VulnerabilityType.INSECURE_DESERIALIZATION,
|
|
376
|
-
severity=Severity.HIGH,
|
|
377
|
-
file_path=str(file_path),
|
|
378
|
-
line_number=line_num,
|
|
379
|
-
description=description,
|
|
380
|
-
evidence=evidence.strip(),
|
|
381
|
-
cwe_id="CWE-502", # Deserialization of Untrusted Data
|
|
382
|
-
remediation="Use safe deserialization methods (json.loads, yaml.safe_load)",
|
|
383
|
-
references=["https://cwe.mitre.org/data/definitions/502.html"],
|
|
384
|
-
)
|
|
385
|
-
vulnerabilities.append(vuln)
|
|
386
|
-
|
|
387
|
-
return vulnerabilities
|
|
388
|
-
|
|
389
|
-
def _scan_for_csrf(
|
|
390
|
-
self,
|
|
391
|
-
file_path: Path,
|
|
392
|
-
content: str,
|
|
393
|
-
lines: list[str],
|
|
394
|
-
) -> list[Vulnerability]:
|
|
395
|
-
"""Scan for CSRF vulnerabilities in web frameworks"""
|
|
396
|
-
vulnerabilities = []
|
|
397
|
-
|
|
398
|
-
# Django/Flask CSRF patterns
|
|
399
|
-
patterns = [
|
|
400
|
-
(
|
|
401
|
-
re.compile(r'@app\.route\(.*methods\s*=\s*\[.*["\']POST["\'].*\]'),
|
|
402
|
-
"POST route without CSRF protection",
|
|
403
|
-
),
|
|
404
|
-
]
|
|
405
|
-
|
|
406
|
-
for pattern, _description in patterns:
|
|
407
|
-
for match in pattern.finditer(content):
|
|
408
|
-
# Check if CSRF protection is present nearby
|
|
409
|
-
line_num = content[: match.start()].count("\n") + 1
|
|
410
|
-
|
|
411
|
-
# Look for CSRF decorators/middleware in surrounding lines
|
|
412
|
-
surrounding_lines = lines[max(0, line_num - 5) : min(len(lines), line_num + 3)]
|
|
413
|
-
has_csrf_protection = any(
|
|
414
|
-
"csrf" in line.lower() or "@login_required" in line
|
|
415
|
-
for line in surrounding_lines
|
|
416
|
-
)
|
|
417
|
-
|
|
418
|
-
if not has_csrf_protection:
|
|
419
|
-
evidence = lines[line_num - 1] if line_num <= len(lines) else ""
|
|
420
|
-
|
|
421
|
-
vuln = Vulnerability(
|
|
422
|
-
vuln_type=VulnerabilityType.CSRF,
|
|
423
|
-
severity=Severity.MEDIUM,
|
|
424
|
-
file_path=str(file_path),
|
|
425
|
-
line_number=line_num,
|
|
426
|
-
description="POST endpoint without CSRF protection",
|
|
427
|
-
evidence=evidence.strip(),
|
|
428
|
-
cwe_id="CWE-352", # Cross-Site Request Forgery
|
|
429
|
-
remediation="Add CSRF protection (e.g., Flask-WTF, Django CSRF middleware)",
|
|
430
|
-
references=["https://cwe.mitre.org/data/definitions/352.html"],
|
|
431
|
-
)
|
|
432
|
-
vulnerabilities.append(vuln)
|
|
433
|
-
|
|
434
|
-
return vulnerabilities
|
|
435
|
-
|
|
436
|
-
def _mask_secret(self, text: str) -> str:
|
|
437
|
-
"""Mask secrets in evidence"""
|
|
438
|
-
# Mask anything that looks like a secret
|
|
439
|
-
masked = re.sub(r'["\'][a-zA-Z0-9_\-/+=]{16,}["\']', '"***REDACTED***"', text)
|
|
440
|
-
return masked
|
|
441
|
-
|
|
442
|
-
def scan_dependencies(
|
|
443
|
-
self,
|
|
444
|
-
requirements_file: Path | None = None,
|
|
445
|
-
) -> list[DependencyVulnerability]:
|
|
446
|
-
"""Scan dependencies for known vulnerabilities using pip-audit
|
|
447
|
-
|
|
448
|
-
Args:
|
|
449
|
-
requirements_file: Path to requirements.txt (optional)
|
|
450
|
-
|
|
451
|
-
Returns:
|
|
452
|
-
List of DependencyVulnerability objects
|
|
453
|
-
|
|
454
|
-
Note: Requires 'pip-audit' to be installed
|
|
455
|
-
|
|
456
|
-
"""
|
|
457
|
-
try:
|
|
458
|
-
# Try to run pip-audit
|
|
459
|
-
cmd = ["pip-audit", "--format", "json"]
|
|
460
|
-
if requirements_file:
|
|
461
|
-
cmd.extend(["-r", str(requirements_file)])
|
|
462
|
-
|
|
463
|
-
result = subprocess.run(cmd, check=False, capture_output=True, text=True, timeout=60)
|
|
464
|
-
|
|
465
|
-
if result.returncode != 0:
|
|
466
|
-
# pip-audit not installed or failed
|
|
467
|
-
return []
|
|
468
|
-
|
|
469
|
-
# Parse JSON output
|
|
470
|
-
data = json.loads(result.stdout)
|
|
471
|
-
return self._parse_pip_audit_output(data)
|
|
472
|
-
|
|
473
|
-
except (subprocess.TimeoutExpired, FileNotFoundError, json.JSONDecodeError):
|
|
474
|
-
# pip-audit not available or failed
|
|
475
|
-
return []
|
|
476
|
-
|
|
477
|
-
def _parse_pip_audit_output(self, data: dict) -> list[DependencyVulnerability]:
|
|
478
|
-
"""Parse pip-audit JSON output"""
|
|
479
|
-
vulnerabilities = []
|
|
480
|
-
|
|
481
|
-
for package_data in data.get("dependencies", []):
|
|
482
|
-
package_name = package_data.get("name", "")
|
|
483
|
-
version = package_data.get("version", "")
|
|
484
|
-
|
|
485
|
-
for vuln in package_data.get("vulns", []):
|
|
486
|
-
cve_id = vuln.get("id", "")
|
|
487
|
-
description = vuln.get("description", "")
|
|
488
|
-
fixed_version = (
|
|
489
|
-
vuln.get("fix_versions", [""])[0] if vuln.get("fix_versions") else None
|
|
490
|
-
)
|
|
491
|
-
|
|
492
|
-
# Parse CVSS score
|
|
493
|
-
cvss_score = 0.0
|
|
494
|
-
if "aliases" in vuln:
|
|
495
|
-
for alias in vuln["aliases"]:
|
|
496
|
-
if "cvss" in alias:
|
|
497
|
-
try:
|
|
498
|
-
cvss_score = float(alias["cvss"])
|
|
499
|
-
except (ValueError, TypeError):
|
|
500
|
-
pass
|
|
501
|
-
|
|
502
|
-
# Determine severity from CVSS
|
|
503
|
-
if cvss_score >= 9.0:
|
|
504
|
-
severity = Severity.CRITICAL
|
|
505
|
-
elif cvss_score >= 7.0:
|
|
506
|
-
severity = Severity.HIGH
|
|
507
|
-
elif cvss_score >= 4.0:
|
|
508
|
-
severity = Severity.MEDIUM
|
|
509
|
-
else:
|
|
510
|
-
severity = Severity.LOW
|
|
511
|
-
|
|
512
|
-
dep_vuln = DependencyVulnerability(
|
|
513
|
-
package_name=package_name,
|
|
514
|
-
installed_version=version,
|
|
515
|
-
vulnerable_versions=f"<{fixed_version}" if fixed_version else "current",
|
|
516
|
-
fixed_version=fixed_version,
|
|
517
|
-
cve_id=cve_id,
|
|
518
|
-
cvss_score=cvss_score,
|
|
519
|
-
severity=severity,
|
|
520
|
-
description=description,
|
|
521
|
-
references=[f"https://nvd.nist.gov/vuln/detail/{cve_id}"],
|
|
522
|
-
)
|
|
523
|
-
vulnerabilities.append(dep_vuln)
|
|
524
|
-
|
|
525
|
-
return vulnerabilities
|
|
526
|
-
|
|
527
|
-
def generate_report(
|
|
528
|
-
self,
|
|
529
|
-
vulnerabilities: list[Vulnerability],
|
|
530
|
-
dependency_vulns: list[DependencyVulnerability],
|
|
531
|
-
files_scanned: int,
|
|
532
|
-
scan_duration: float,
|
|
533
|
-
) -> VulnerabilityScanReport:
|
|
534
|
-
"""Generate comprehensive scan report"""
|
|
535
|
-
# Count by severity
|
|
536
|
-
critical_count = sum(1 for v in vulnerabilities if v.severity == Severity.CRITICAL)
|
|
537
|
-
high_count = sum(1 for v in vulnerabilities if v.severity == Severity.HIGH)
|
|
538
|
-
medium_count = sum(1 for v in vulnerabilities if v.severity == Severity.MEDIUM)
|
|
539
|
-
low_count = sum(1 for v in vulnerabilities if v.severity == Severity.LOW)
|
|
540
|
-
info_count = sum(1 for v in vulnerabilities if v.severity == Severity.INFO)
|
|
541
|
-
|
|
542
|
-
# Add dependency vulnerabilities to counts
|
|
543
|
-
critical_count += sum(1 for v in dependency_vulns if v.severity == Severity.CRITICAL)
|
|
544
|
-
high_count += sum(1 for v in dependency_vulns if v.severity == Severity.HIGH)
|
|
545
|
-
medium_count += sum(1 for v in dependency_vulns if v.severity == Severity.MEDIUM)
|
|
546
|
-
low_count += sum(1 for v in dependency_vulns if v.severity == Severity.LOW)
|
|
547
|
-
|
|
548
|
-
return VulnerabilityScanReport(
|
|
549
|
-
total_issues=len(vulnerabilities) + len(dependency_vulns),
|
|
550
|
-
critical_count=critical_count,
|
|
551
|
-
high_count=high_count,
|
|
552
|
-
medium_count=medium_count,
|
|
553
|
-
low_count=low_count,
|
|
554
|
-
info_count=info_count,
|
|
555
|
-
vulnerabilities=vulnerabilities,
|
|
556
|
-
dependency_vulnerabilities=dependency_vulns,
|
|
557
|
-
files_scanned=files_scanned,
|
|
558
|
-
scan_duration=scan_duration,
|
|
559
|
-
)
|
|
560
|
-
|
|
561
|
-
def generate_summary(self, report: VulnerabilityScanReport) -> str:
|
|
562
|
-
"""Generate human-readable summary"""
|
|
563
|
-
summary = []
|
|
564
|
-
summary.append("=" * 70)
|
|
565
|
-
summary.append("SECURITY VULNERABILITY SCAN REPORT")
|
|
566
|
-
summary.append("=" * 70)
|
|
567
|
-
summary.append(f"Files Scanned: {report.files_scanned}")
|
|
568
|
-
summary.append(f"Scan Duration: {report.scan_duration:.2f}s")
|
|
569
|
-
summary.append(f"Total Issues Found: {report.total_issues}")
|
|
570
|
-
summary.append("")
|
|
571
|
-
summary.append("Severity Breakdown:")
|
|
572
|
-
summary.append(f" š“ CRITICAL: {report.critical_count}")
|
|
573
|
-
summary.append(f" š HIGH: {report.high_count}")
|
|
574
|
-
summary.append(f" š” MEDIUM: {report.medium_count}")
|
|
575
|
-
summary.append(f" šµ LOW: {report.low_count}")
|
|
576
|
-
summary.append(f" āŖ INFO: {report.info_count}")
|
|
577
|
-
summary.append("")
|
|
578
|
-
|
|
579
|
-
if report.critical_count > 0 or report.high_count > 0:
|
|
580
|
-
summary.append("ā ļø CRITICAL & HIGH SEVERITY ISSUES:")
|
|
581
|
-
critical_high = [
|
|
582
|
-
v
|
|
583
|
-
for v in report.vulnerabilities
|
|
584
|
-
if v.severity in [Severity.CRITICAL, Severity.HIGH]
|
|
585
|
-
]
|
|
586
|
-
for vuln in critical_high[:5]:
|
|
587
|
-
summary.append(f"\n {vuln.severity.value.upper()}: {vuln.description}")
|
|
588
|
-
summary.append(f" File: {vuln.file_path}:{vuln.line_number}")
|
|
589
|
-
summary.append(f" Type: {vuln.vuln_type.value}")
|
|
590
|
-
if vuln.cwe_id:
|
|
591
|
-
summary.append(f" CWE: {vuln.cwe_id}")
|
|
592
|
-
|
|
593
|
-
if report.dependency_vulnerabilities:
|
|
594
|
-
summary.append("\nš¦ DEPENDENCY VULNERABILITIES:")
|
|
595
|
-
for dep_vuln in report.dependency_vulnerabilities[:5]:
|
|
596
|
-
summary.append(f"\n {dep_vuln.package_name} {dep_vuln.installed_version}")
|
|
597
|
-
summary.append(f" {dep_vuln.cve_id} - {dep_vuln.severity.value.upper()}")
|
|
598
|
-
summary.append(f" CVSS: {dep_vuln.cvss_score}")
|
|
599
|
-
if dep_vuln.fixed_version:
|
|
600
|
-
summary.append(f" Fix: Upgrade to {dep_vuln.fixed_version}")
|
|
601
|
-
|
|
602
|
-
summary.append("\n" + "=" * 70)
|
|
603
|
-
|
|
604
|
-
return "\n".join(summary)
|