diff --git a/backend/services/risks_service.py b/backend/services/risks_service.py index 2593109..57d7a71 100644 --- a/backend/services/risks_service.py +++ b/backend/services/risks_service.py @@ -33,11 +33,19 @@ def get_risks(user_id): for scan in scans: scan_result = scan.scan_result scan_type = scan.scan_type - failed_checks = scan_result.get("results", {}).get("failed_checks", []) - + if "failed_checks" in scan_result: + failed_checks = scan_result["failed_checks"] + elif "results" in scan_result and "failed_checks" in scan_result["results"]: + failed_checks = scan_result["results"]["failed_checks"] for check in failed_checks: - severity = check.get("severity", "INFO") - severity_counts[severity] = severity_counts.get(severity, 0) + 1 + severity = check.get("severity") or "INFO" # Handles None explicitly + # Normalize to uppercase for counting (in case Checkov uses "high" or "High") + severity_upper = severity.upper() if severity else "INFO" + # Only count if it's one of our expected keys (avoids errors if weird values) + if severity_upper in severity_counts: + severity_counts[severity_upper] += 1 + else: + severity_counts["INFO"] += 1 # Fallback for unknown severities detailed_risks.append({ "severity": severity, "check_id": check.get("check_id"), diff --git a/frontend/src/components/VulnerabilityScanner/GitHubScanner.jsx b/frontend/src/components/VulnerabilityScanner/GitHubScanner.jsx index 58e2ed9..8aa9c92 100644 --- a/frontend/src/components/VulnerabilityScanner/GitHubScanner.jsx +++ b/frontend/src/components/VulnerabilityScanner/GitHubScanner.jsx @@ -23,7 +23,6 @@ const GitHubScanner = ({ setResult, isLoading, setIsLoading }) => { formData.append("input_type", "repo"); formData.append("repo_url", url); - console.log("Sending request to backend with URL:", url); const response = await fetch("http://localhost:5000/semgrep", { method: "POST", headers: { diff --git a/frontend/src/pages/RiskDashboard/RiskDashboard.css b/frontend/src/pages/RiskDashboard/RiskDashboard.css index 3a54f1a..ea100c9 100644 --- a/frontend/src/pages/RiskDashboard/RiskDashboard.css +++ b/frontend/src/pages/RiskDashboard/RiskDashboard.css @@ -499,4 +499,87 @@ .vulnerability-table__scroll::-webkit-scrollbar, .vulnerability-table__cards::-webkit-scrollbar { width: 8px; +} +/* Scan Type Filter Styles */ +.scan-type-filter { + background: #fff; + border-radius: 8px; + padding: 1.5rem; + margin-bottom: 1.5rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.scan-type-filter__label { + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 600; + font-size: 0.875rem; + color: #374151; + margin-bottom: 1rem; +} + +.scan-type-filter__icon { + width: 1.25rem; + height: 1.25rem; + color: #6b7280; +} + +.scan-type-filter__buttons { + display: flex; + gap: 0.75rem; + flex-wrap: wrap; +} + +.scan-type-filter__button { + padding: 0.5rem 1rem; + border: 2px solid #e5e7eb; + border-radius: 6px; + background: #fff; + color: #6b7280; + font-weight: 500; + cursor: pointer; + transition: all 0.2s; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.scan-type-filter__button:hover { + border-color: #3b82f6; + color: #3b82f6; + background: #eff6ff; +} + +.scan-type-filter__button--active { + border-color: #3b82f6; + background: #3b82f6; + color: #fff; +} + +.scan-type-filter__count { + font-size: 0.75rem; + opacity: 0.8; +} + +/* Update vulnerability table styles */ +.vulnerability-table__scan-type { + display: inline-block; + padding: 0.25rem 0.75rem; + border-radius: 4px; + background: #f3f4f6; + color: #374151; + font-size: 0.875rem; + font-weight: 600; + text-transform: uppercase; +} + +.vulnerability-card__scan-type { + padding: 0.25rem 0.625rem; + border-radius: 4px; + background: #f3f4f6; + color: #374151; + font-size: 0.75rem; + font-weight: 600; + text-transform: uppercase; } \ No newline at end of file diff --git a/frontend/src/pages/RiskDashboard/RiskDashboard.jsx b/frontend/src/pages/RiskDashboard/RiskDashboard.jsx index 3497e8d..b1edb95 100644 --- a/frontend/src/pages/RiskDashboard/RiskDashboard.jsx +++ b/frontend/src/pages/RiskDashboard/RiskDashboard.jsx @@ -1,5 +1,5 @@ -import React from 'react'; -import { ChartBarIcon, ArrowPathIcon, ExclamationCircleIcon } from '@heroicons/react/24/outline'; +import React, { useState } from 'react'; +import { ChartBarIcon, ArrowPathIcon, ExclamationCircleIcon, FunnelIcon } from '@heroicons/react/24/outline'; import { Bar } from 'react-chartjs-2'; import { useRisks } from '../../hooks/UseRisk'; import { createChartData, createChartOptions, getSeverityColor } from '../../utils/chartConfig'; @@ -7,6 +7,37 @@ import './RiskDashboard.css'; const RiskDashboardPage = () => { const { risks, details, loading, error, isRefreshing, refreshRisks } = useRisks(); + const [selectedScanType, setSelectedScanType] = useState('all'); + + // Get unique scan types from details + const scanTypes = ['all', ...new Set(details.map(d => d.scan_type).filter(Boolean))]; + + // Filter details based on selected scan type + const filteredDetails = selectedScanType === 'all' + ? details + : details.filter(d => d.scan_type === selectedScanType); + + // Aggregate risks by severity for filtered data + const getFilteredRisks = () => { + if (selectedScanType === 'all') return risks; + + const severityCounts = { ERROR: 0, WARNING: 0, INFO: 0 }; + + filteredDetails.forEach(detail => { + const severity = (detail.severity || 'INFO').toUpperCase(); + if (severity in severityCounts) { + severityCounts[severity] += 1; + } else { + severityCounts.INFO += 1; + } + }); + + return [ + { name: "Critical (ERROR)", level: severityCounts.ERROR * 10 }, + { name: "High (WARNING)", level: severityCounts.WARNING * 5 }, + { name: "Low (INFO)", level: severityCounts.INFO * 2 } + ]; + }; // Loading Spinner Component const LoadingSpinner = ({ message = 'Loading...' }) => ( @@ -34,10 +65,39 @@ const RiskDashboardPage = () => { ); + // Scan Type Filter Component + const ScanTypeFilter = () => ( +
+
+ + Filter by Scan Type: +
+
+ {scanTypes.map(type => ( + + ))} +
+
+ ); + // Risk Chart Section const RiskChart = ({ risks }) => { - const chartData = createChartData(risks); - const chartOptions = createChartOptions(risks); + const filteredRisks = getFilteredRisks(); + const chartData = createChartData(filteredRisks); + const chartOptions = createChartOptions(filteredRisks); return (
@@ -58,7 +118,7 @@ const RiskDashboardPage = () => {

Vulnerability Details

-

No vulnerabilities found

+

No vulnerabilities found{selectedScanType !== 'all' ? ` for ${selectedScanType}` : ''}

); @@ -67,7 +127,7 @@ const RiskDashboardPage = () => { return (

- Vulnerability Details ({details.length}) + Vulnerabilities Details ({details.length})

{/* Desktop Table */} @@ -76,6 +136,7 @@ const RiskDashboardPage = () => { + @@ -84,6 +145,11 @@ const RiskDashboardPage = () => { {details.map((detail, index) => ( +
Scan Type Severity Problem Suggestion
+ + {detail.scan_type || 'N/A'} + + { {details.map((detail, index) => (
+ + {detail.scan_type || 'N/A'} + { return ( <> + - + ); };