Spaces:
Running on CPU Upgrade
Running on CPU Upgrade
Update frontend/src/pages/LogsAndThreats.jsx
Browse files- frontend/src/pages/LogsAndThreats.jsx +185 -149
frontend/src/pages/LogsAndThreats.jsx
CHANGED
|
@@ -199,16 +199,25 @@ const LogsAndThreats = () => {
|
|
| 199 |
const getThreatDetail = (t) => {
|
| 200 |
if (!t) return null;
|
| 201 |
const titleKey = typeof t === 'string' ? t : (t.title || '');
|
| 202 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 203 |
return {
|
| 204 |
-
title: titleKey,
|
| 205 |
count: t.count || 1,
|
| 206 |
severity: t.severity || kb.severity || 'Medium',
|
| 207 |
category: t.category || kb.category || 'Security Headers',
|
| 208 |
-
cvss: t.cvss_score || kb.cvss || 5.3,
|
| 209 |
-
owasp: t.owasp_category || kb.owasp || 'A05:2021 - Security Misconfiguration',
|
| 210 |
cwe: t.cwe_ids && t.cwe_ids.length ? t.cwe_ids : (kb.cwe || ['CWE-693']),
|
| 211 |
-
description: t.description && t.description.length >
|
| 212 |
impact: t.impact || kb.impact || 'Unpatched or missing security settings increase risk of exploitation, unauthorized data access, or service disruption.',
|
| 213 |
remediation: t.remediation && t.remediation.length > 20 ? t.remediation : (kb.remediation || 'add_header Cross-Origin-Embedder-Policy "require-corp" always;'),
|
| 214 |
affected_targets: t.affected_targets && t.affected_targets.length ? t.affected_targets : (kb.affected_targets || ['https://app.larshield.io'])
|
|
@@ -224,8 +233,35 @@ const LogsAndThreats = () => {
|
|
| 224 |
return 'bg-blue-500/15 text-blue-600 dark:text-blue-400 border-blue-500/30';
|
| 225 |
};
|
| 226 |
|
| 227 |
-
// Threat Details Calculations
|
| 228 |
-
const
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 229 |
|
| 230 |
// Stats Counters
|
| 231 |
const criticalCount = allThreatDetails.filter(t => t.severity.toLowerCase() === 'critical').length;
|
|
@@ -426,6 +462,142 @@ const LogsAndThreats = () => {
|
|
| 426 |
);
|
| 427 |
}
|
| 428 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 429 |
// Full Page Threat Intelligence View Mode
|
| 430 |
if (isFullThreatsView) {
|
| 431 |
return (
|
|
@@ -655,8 +827,7 @@ const LogsAndThreats = () => {
|
|
| 655 |
return (
|
| 656 |
<tr
|
| 657 |
key={i}
|
| 658 |
-
|
| 659 |
-
className="hover:bg-surface-container-high/60 transition-colors cursor-pointer group"
|
| 660 |
>
|
| 661 |
<td className="p-3.5 text-center font-extrabold text-[12px] text-error">
|
| 662 |
{rowIdx}
|
|
@@ -773,10 +944,10 @@ const LogsAndThreats = () => {
|
|
| 773 |
</>
|
| 774 |
)}
|
| 775 |
</div>
|
|
|
|
| 776 |
</div>
|
| 777 |
);
|
| 778 |
}
|
| 779 |
-
|
| 780 |
// Full Page Audit Logs Mode
|
| 781 |
if (isFullLogsView) {
|
| 782 |
return (
|
|
@@ -991,6 +1162,7 @@ const LogsAndThreats = () => {
|
|
| 991 |
</>
|
| 992 |
)}
|
| 993 |
</div>
|
|
|
|
| 994 |
</div>
|
| 995 |
);
|
| 996 |
}
|
|
@@ -1041,12 +1213,7 @@ const LogsAndThreats = () => {
|
|
| 1041 |
return (
|
| 1042 |
<li
|
| 1043 |
key={i}
|
| 1044 |
-
|
| 1045 |
-
e.preventDefault();
|
| 1046 |
-
setSelectedThreat(detail);
|
| 1047 |
-
}}
|
| 1048 |
-
className="py-3 px-3 rounded-xl flex flex-col sm:flex-row sm:items-center justify-between gap-3 hover:bg-surface-container-high/70 cursor-pointer transition-all group border border-transparent hover:border-primary/30 my-1"
|
| 1049 |
-
title="Click to view full threat details & remediation guide"
|
| 1050 |
>
|
| 1051 |
<div className="flex items-start gap-3 pr-2">
|
| 1052 |
<span className="w-7 h-7 rounded-full bg-error/10 text-error flex items-center justify-center text-[12px] font-extrabold shrink-0 mt-0.5 border border-error/20">
|
|
@@ -1191,139 +1358,8 @@ const LogsAndThreats = () => {
|
|
| 1191 |
</div>
|
| 1192 |
</div>
|
| 1193 |
|
| 1194 |
-
{/* Global Threat Detail Modal
|
| 1195 |
-
{selectedThreat && (
|
| 1196 |
-
<div className="fixed inset-0 bg-black/80 backdrop-blur-md flex items-center justify-center p-4 pt-20 z-[9999] animate-fade-in overflow-y-auto">
|
| 1197 |
-
<div className="bg-surface border border-outline-variant rounded-2xl max-w-2xl w-full shadow-2xl relative my-auto overflow-hidden flex flex-col max-h-[85vh]">
|
| 1198 |
-
|
| 1199 |
-
{/* Header Banner with Gradient */}
|
| 1200 |
-
<div className="bg-gradient-to-r from-surface-container-highest via-surface-container to-surface-container-low p-6 border-b border-outline-variant relative">
|
| 1201 |
-
<button
|
| 1202 |
-
onClick={() => setSelectedThreat(null)}
|
| 1203 |
-
className="absolute top-4 right-4 text-on-surface-variant hover:text-on-surface bg-surface-container-high p-2 rounded-full transition-colors cursor-pointer border border-outline-variant/60"
|
| 1204 |
-
>
|
| 1205 |
-
<X className="w-5 h-5" />
|
| 1206 |
-
</button>
|
| 1207 |
-
|
| 1208 |
-
<div className="flex items-center gap-2 flex-wrap mb-3 pr-10">
|
| 1209 |
-
<span className={`px-3 py-1 rounded-full text-[11px] font-black uppercase tracking-wider border shadow-2xs ${getSeverityBadgeClass(selectedThreat.severity)}`}>
|
| 1210 |
-
{selectedThreat.severity} SEVERITY
|
| 1211 |
-
</span>
|
| 1212 |
-
<span className="bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black px-3 py-1 rounded-full border border-cyan-500/30">
|
| 1213 |
-
CVSS {selectedThreat.cvss}
|
| 1214 |
-
</span>
|
| 1215 |
-
<span className="bg-red-500/10 text-red-600 dark:text-red-400 text-[11px] font-black px-3 py-1 rounded-full border border-red-500/30 flex items-center gap-1">
|
| 1216 |
-
<ShieldAlert className="w-3.5 h-3.5" />
|
| 1217 |
-
{selectedThreat.count} Detections Recorded
|
| 1218 |
-
</span>
|
| 1219 |
-
</div>
|
| 1220 |
-
|
| 1221 |
-
<h2 className="text-[21px] font-extrabold text-on-surface tracking-tight leading-snug">
|
| 1222 |
-
{selectedThreat.title}
|
| 1223 |
-
</h2>
|
| 1224 |
-
</div>
|
| 1225 |
-
|
| 1226 |
-
{/* Modal Body Scroll Container */}
|
| 1227 |
-
<div className="p-6 space-y-5 overflow-y-auto text-[13.5px]">
|
| 1228 |
-
|
| 1229 |
-
{/* Category & OWASP Specifications Cards */}
|
| 1230 |
-
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
| 1231 |
-
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
|
| 1232 |
-
<span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
|
| 1233 |
-
<Layers className="w-3.5 h-3.5 text-primary" /> Vulnerability Category
|
| 1234 |
-
</span>
|
| 1235 |
-
<span className="font-extrabold text-on-surface text-[14px]">{selectedThreat.category}</span>
|
| 1236 |
-
</div>
|
| 1237 |
-
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
|
| 1238 |
-
<span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
|
| 1239 |
-
<Shield className="w-3.5 h-3.5 text-primary" /> OWASP Standard
|
| 1240 |
-
</span>
|
| 1241 |
-
<span className="font-extrabold text-primary text-[14px]">{selectedThreat.owasp}</span>
|
| 1242 |
-
</div>
|
| 1243 |
-
</div>
|
| 1244 |
-
|
| 1245 |
-
{/* Threat Overview Card */}
|
| 1246 |
-
<div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-primary border border-outline-variant/60 shadow-2xs">
|
| 1247 |
-
<h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2">
|
| 1248 |
-
<Shield className="w-4 h-4 text-primary" /> Threat Overview
|
| 1249 |
-
</h3>
|
| 1250 |
-
<p className="text-on-surface-variant leading-relaxed">
|
| 1251 |
-
{selectedThreat.description}
|
| 1252 |
-
</p>
|
| 1253 |
-
</div>
|
| 1254 |
-
|
| 1255 |
-
{/* Security Impact Card */}
|
| 1256 |
-
<div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-amber-500 border border-outline-variant/60 shadow-2xs">
|
| 1257 |
-
<h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2 text-amber-600 dark:text-amber-400">
|
| 1258 |
-
<AlertTriangle className="w-4 h-4" /> Exploitation & Impact Risk
|
| 1259 |
-
</h3>
|
| 1260 |
-
<p className="text-on-surface-variant leading-relaxed">
|
| 1261 |
-
{selectedThreat.impact}
|
| 1262 |
-
</p>
|
| 1263 |
-
</div>
|
| 1264 |
-
|
| 1265 |
-
{/* Code Remediation Terminal Box */}
|
| 1266 |
-
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
|
| 1267 |
-
<div className="flex items-center justify-between mb-2">
|
| 1268 |
-
<h3 className="font-bold text-on-surface text-[14px] flex items-center gap-2 text-green-600 dark:text-green-400">
|
| 1269 |
-
<Terminal className="w-4 h-4" /> Recommended Remediation Command
|
| 1270 |
-
</h3>
|
| 1271 |
-
<button
|
| 1272 |
-
onClick={() => copyToClipboard(selectedThreat.remediation)}
|
| 1273 |
-
className="flex items-center gap-1 px-2.5 py-1 bg-surface-container hover:bg-surface-container-high text-on-surface rounded-lg text-[11.5px] font-bold border border-outline-variant cursor-pointer transition-all"
|
| 1274 |
-
>
|
| 1275 |
-
{copiedCode ? <Check className="w-3.5 h-3.5 text-green-500" /> : <Copy className="w-3.5 h-3.5" />}
|
| 1276 |
-
{copiedCode ? 'Copied!' : 'Copy Code'}
|
| 1277 |
-
</button>
|
| 1278 |
-
</div>
|
| 1279 |
-
|
| 1280 |
-
<div className="bg-[#0b132a] text-[#38bdf8] font-mono text-[12.5px] p-4 rounded-xl border border-slate-800 leading-relaxed overflow-x-auto shadow-inner">
|
| 1281 |
-
{selectedThreat.remediation}
|
| 1282 |
-
</div>
|
| 1283 |
-
</div>
|
| 1284 |
-
|
| 1285 |
-
{/* Affected Target Endpoints */}
|
| 1286 |
-
{selectedThreat.affected_targets && selectedThreat.affected_targets.length > 0 && (
|
| 1287 |
-
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
|
| 1288 |
-
<h3 className="font-bold text-on-surface text-[14px] mb-2.5 flex items-center gap-2">
|
| 1289 |
-
<ExternalLink className="w-4 h-4 text-primary" /> Affected Target Endpoints ({selectedThreat.affected_targets.length})
|
| 1290 |
-
</h3>
|
| 1291 |
-
<div className="flex flex-wrap gap-2">
|
| 1292 |
-
{selectedThreat.affected_targets.map((url, idx) => (
|
| 1293 |
-
<span key={idx} className="bg-surface-container border border-outline-variant/80 text-on-surface font-mono text-[12px] px-3 py-1.5 rounded-lg flex items-center gap-2 font-medium">
|
| 1294 |
-
<span className="w-2 h-2 rounded-full bg-red-500 animate-pulse"></span>
|
| 1295 |
-
{url}
|
| 1296 |
-
</span>
|
| 1297 |
-
))}
|
| 1298 |
-
</div>
|
| 1299 |
-
</div>
|
| 1300 |
-
)}
|
| 1301 |
-
</div>
|
| 1302 |
-
|
| 1303 |
-
{/* Modal Actions Footer */}
|
| 1304 |
-
<div className="p-4 bg-surface-container-lowest border-t border-outline-variant flex items-center justify-between flex-wrap gap-3">
|
| 1305 |
-
<button
|
| 1306 |
-
onClick={() => {
|
| 1307 |
-
const query = selectedThreat.title;
|
| 1308 |
-
setSelectedThreat(null);
|
| 1309 |
-
openFullLogsView(query);
|
| 1310 |
-
}}
|
| 1311 |
-
className="px-4 py-2.5 bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-xl font-bold text-[13px] flex items-center gap-2 cursor-pointer transition-colors"
|
| 1312 |
-
>
|
| 1313 |
-
<Search className="w-4 h-4" />
|
| 1314 |
-
Filter Audit Logs for this Threat
|
| 1315 |
-
</button>
|
| 1316 |
-
|
| 1317 |
-
<button
|
| 1318 |
-
onClick={() => setSelectedThreat(null)}
|
| 1319 |
-
className="px-6 py-2.5 bg-primary text-white hover:brightness-110 rounded-xl font-bold text-[13px] cursor-pointer border-0 shadow-md shadow-primary/20 transition-all"
|
| 1320 |
-
>
|
| 1321 |
-
Close Window
|
| 1322 |
-
</button>
|
| 1323 |
-
</div>
|
| 1324 |
-
</div>
|
| 1325 |
-
</div>
|
| 1326 |
-
)}
|
| 1327 |
</div>
|
| 1328 |
);
|
| 1329 |
};
|
|
|
|
| 199 |
const getThreatDetail = (t) => {
|
| 200 |
if (!t) return null;
|
| 201 |
const titleKey = typeof t === 'string' ? t : (t.title || '');
|
| 202 |
+
|
| 203 |
+
// Intelligent fuzzy matching for Knowledge Base lookup
|
| 204 |
+
const kbKey = Object.keys(THREAT_KNOWLEDGE_BASE).find(k =>
|
| 205 |
+
k.toLowerCase() === titleKey.toLowerCase() ||
|
| 206 |
+
titleKey.toLowerCase().includes(k.toLowerCase()) ||
|
| 207 |
+
k.toLowerCase().includes(titleKey.toLowerCase()) ||
|
| 208 |
+
(titleKey.toLowerCase().includes('cve') && k.toLowerCase().includes('cve'))
|
| 209 |
+
);
|
| 210 |
+
const kb = (kbKey ? THREAT_KNOWLEDGE_BASE[kbKey] : null) || {};
|
| 211 |
+
|
| 212 |
return {
|
| 213 |
+
title: titleKey || kbKey || 'Security Vulnerability',
|
| 214 |
count: t.count || 1,
|
| 215 |
severity: t.severity || kb.severity || 'Medium',
|
| 216 |
category: t.category || kb.category || 'Security Headers',
|
| 217 |
+
cvss: t.cvss_score || t.cvss || kb.cvss || 5.3,
|
| 218 |
+
owasp: t.owasp_category || t.owasp || kb.owasp || 'A05:2021 - Security Misconfiguration',
|
| 219 |
cwe: t.cwe_ids && t.cwe_ids.length ? t.cwe_ids : (kb.cwe || ['CWE-693']),
|
| 220 |
+
description: t.description && t.description.length > 20 ? t.description : (kb.description || `Security intelligence scan detected "${titleKey}" across active system endpoints.`),
|
| 221 |
impact: t.impact || kb.impact || 'Unpatched or missing security settings increase risk of exploitation, unauthorized data access, or service disruption.',
|
| 222 |
remediation: t.remediation && t.remediation.length > 20 ? t.remediation : (kb.remediation || 'add_header Cross-Origin-Embedder-Policy "require-corp" always;'),
|
| 223 |
affected_targets: t.affected_targets && t.affected_targets.length ? t.affected_targets : (kb.affected_targets || ['https://app.larshield.io'])
|
|
|
|
| 233 |
return 'bg-blue-500/15 text-blue-600 dark:text-blue-400 border-blue-500/30';
|
| 234 |
};
|
| 235 |
|
| 236 |
+
// Threat Details Calculations (Merge KB + Live API Trends)
|
| 237 |
+
const mergedThreatsMap = new Map();
|
| 238 |
+
Object.keys(THREAT_KNOWLEDGE_BASE).forEach(key => {
|
| 239 |
+
mergedThreatsMap.set(key, getThreatDetail({ title: key, count: 1 }));
|
| 240 |
+
});
|
| 241 |
+
|
| 242 |
+
if (Array.isArray(trends) && trends.length > 0) {
|
| 243 |
+
trends.forEach(t => {
|
| 244 |
+
const detail = getThreatDetail(t);
|
| 245 |
+
if (detail && detail.title) {
|
| 246 |
+
const existingKey = Array.from(mergedThreatsMap.keys()).find(k =>
|
| 247 |
+
k.toLowerCase() === detail.title.toLowerCase() ||
|
| 248 |
+
k.toLowerCase().includes(detail.title.toLowerCase()) ||
|
| 249 |
+
detail.title.toLowerCase().includes(k.toLowerCase())
|
| 250 |
+
);
|
| 251 |
+
if (existingKey) {
|
| 252 |
+
mergedThreatsMap.set(existingKey, {
|
| 253 |
+
...mergedThreatsMap.get(existingKey),
|
| 254 |
+
...detail,
|
| 255 |
+
count: detail.count || mergedThreatsMap.get(existingKey).count || 1
|
| 256 |
+
});
|
| 257 |
+
} else {
|
| 258 |
+
mergedThreatsMap.set(detail.title, detail);
|
| 259 |
+
}
|
| 260 |
+
}
|
| 261 |
+
});
|
| 262 |
+
}
|
| 263 |
+
|
| 264 |
+
const allThreatDetails = Array.from(mergedThreatsMap.values());
|
| 265 |
|
| 266 |
// Stats Counters
|
| 267 |
const criticalCount = allThreatDetails.filter(t => t.severity.toLowerCase() === 'critical').length;
|
|
|
|
| 462 |
);
|
| 463 |
}
|
| 464 |
|
| 465 |
+
const renderThreatModal = () => {
|
| 466 |
+
if (!selectedThreat) return null;
|
| 467 |
+
return (
|
| 468 |
+
<div className="fixed inset-0 bg-black/80 backdrop-blur-md flex items-center justify-center p-4 pt-20 z-[9999] animate-fade-in overflow-y-auto">
|
| 469 |
+
<div className="bg-surface border border-outline-variant rounded-2xl max-w-2xl w-full shadow-2xl relative my-auto overflow-hidden flex flex-col max-h-[85vh]">
|
| 470 |
+
|
| 471 |
+
{/* Header Banner with Gradient */}
|
| 472 |
+
<div className="bg-gradient-to-r from-surface-container-highest via-surface-container to-surface-container-low p-6 border-b border-outline-variant relative">
|
| 473 |
+
<button
|
| 474 |
+
onClick={() => setSelectedThreat(null)}
|
| 475 |
+
className="absolute top-4 right-4 text-on-surface-variant hover:text-on-surface bg-surface-container-high p-2 rounded-full transition-colors cursor-pointer border border-outline-variant/60"
|
| 476 |
+
>
|
| 477 |
+
<X className="w-5 h-5" />
|
| 478 |
+
</button>
|
| 479 |
+
|
| 480 |
+
<div className="flex items-center gap-2 flex-wrap mb-3 pr-10">
|
| 481 |
+
<span className={`px-3 py-1 rounded-full text-[11px] font-black uppercase tracking-wider border shadow-2xs ${getSeverityBadgeClass(selectedThreat.severity)}`}>
|
| 482 |
+
{selectedThreat.severity} SEVERITY
|
| 483 |
+
</span>
|
| 484 |
+
<span className="bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black px-3 py-1 rounded-full border border-cyan-500/30">
|
| 485 |
+
CVSS {selectedThreat.cvss}
|
| 486 |
+
</span>
|
| 487 |
+
<span className="bg-red-500/10 text-red-600 dark:text-red-400 text-[11px] font-black px-3 py-1 rounded-full border border-red-500/30 flex items-center gap-1">
|
| 488 |
+
<ShieldAlert className="w-3.5 h-3.5" />
|
| 489 |
+
{selectedThreat.count} Detections Recorded
|
| 490 |
+
</span>
|
| 491 |
+
</div>
|
| 492 |
+
|
| 493 |
+
<h2 className="text-[21px] font-extrabold text-on-surface tracking-tight leading-snug">
|
| 494 |
+
{selectedThreat.title}
|
| 495 |
+
</h2>
|
| 496 |
+
</div>
|
| 497 |
+
|
| 498 |
+
{/* Modal Body Scroll Container */}
|
| 499 |
+
<div className="p-6 space-y-5 overflow-y-auto text-[13.5px]">
|
| 500 |
+
|
| 501 |
+
{/* Category & OWASP Specifications Cards */}
|
| 502 |
+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
| 503 |
+
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
|
| 504 |
+
<span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
|
| 505 |
+
<Layers className="w-3.5 h-3.5 text-primary" /> Vulnerability Category
|
| 506 |
+
</span>
|
| 507 |
+
<span className="font-extrabold text-on-surface text-[14px]">{selectedThreat.category}</span>
|
| 508 |
+
</div>
|
| 509 |
+
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/70 shadow-2xs">
|
| 510 |
+
<span className="text-[11px] font-bold text-on-surface-variant uppercase tracking-wider flex items-center gap-1.5 mb-1">
|
| 511 |
+
<Shield className="w-3.5 h-3.5 text-primary" /> OWASP Standard
|
| 512 |
+
</span>
|
| 513 |
+
<span className="font-extrabold text-primary text-[14px]">{selectedThreat.owasp}</span>
|
| 514 |
+
</div>
|
| 515 |
+
</div>
|
| 516 |
+
|
| 517 |
+
{/* Threat Overview Card */}
|
| 518 |
+
<div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-primary border border-outline-variant/60 shadow-2xs">
|
| 519 |
+
<h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2">
|
| 520 |
+
<Shield className="w-4 h-4 text-primary" /> Threat Overview
|
| 521 |
+
</h3>
|
| 522 |
+
<p className="text-on-surface-variant leading-relaxed">
|
| 523 |
+
{selectedThreat.description}
|
| 524 |
+
</p>
|
| 525 |
+
</div>
|
| 526 |
+
|
| 527 |
+
{/* Security Impact Card */}
|
| 528 |
+
<div className="bg-surface-container-lowest p-4 rounded-xl border-l-4 border-l-amber-500 border border-outline-variant/60 shadow-2xs">
|
| 529 |
+
<h3 className="font-bold text-on-surface text-[14px] mb-2 flex items-center gap-2 text-amber-600 dark:text-amber-400">
|
| 530 |
+
<AlertTriangle className="w-4 h-4" /> Exploitation & Impact Risk
|
| 531 |
+
</h3>
|
| 532 |
+
<p className="text-on-surface-variant leading-relaxed">
|
| 533 |
+
{selectedThreat.impact}
|
| 534 |
+
</p>
|
| 535 |
+
</div>
|
| 536 |
+
|
| 537 |
+
{/* Code Remediation Terminal Box */}
|
| 538 |
+
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
|
| 539 |
+
<div className="flex items-center justify-between mb-2">
|
| 540 |
+
<h3 className="font-bold text-on-surface text-[14px] flex items-center gap-2 text-green-600 dark:text-green-400">
|
| 541 |
+
<Terminal className="w-4 h-4" /> Recommended Remediation Command
|
| 542 |
+
</h3>
|
| 543 |
+
<button
|
| 544 |
+
onClick={() => copyToClipboard(selectedThreat.remediation)}
|
| 545 |
+
className="flex items-center gap-1 px-2.5 py-1 bg-surface-container hover:bg-surface-container-high text-on-surface rounded-lg text-[11.5px] font-bold border border-outline-variant cursor-pointer transition-all"
|
| 546 |
+
>
|
| 547 |
+
{copiedCode ? <Check className="w-3.5 h-3.5 text-green-500" /> : <Copy className="w-3.5 h-3.5" />}
|
| 548 |
+
{copiedCode ? 'Copied!' : 'Copy Code'}
|
| 549 |
+
</button>
|
| 550 |
+
</div>
|
| 551 |
+
|
| 552 |
+
<div className="bg-[#0b132a] text-[#38bdf8] font-mono text-[12.5px] p-4 rounded-xl border border-slate-800 leading-relaxed overflow-x-auto shadow-inner whitespace-pre-wrap">
|
| 553 |
+
{selectedThreat.remediation}
|
| 554 |
+
</div>
|
| 555 |
+
</div>
|
| 556 |
+
|
| 557 |
+
{/* Affected Target Endpoints */}
|
| 558 |
+
{selectedThreat.affected_targets && selectedThreat.affected_targets.length > 0 && (
|
| 559 |
+
<div className="bg-surface-container-lowest p-4 rounded-xl border border-outline-variant/60 shadow-2xs">
|
| 560 |
+
<h3 className="font-bold text-on-surface text-[14px] mb-2.5 flex items-center gap-2">
|
| 561 |
+
<ExternalLink className="w-4 h-4 text-primary" /> Affected Target Endpoints ({selectedThreat.affected_targets.length})
|
| 562 |
+
</h3>
|
| 563 |
+
<div className="flex flex-wrap gap-2">
|
| 564 |
+
{selectedThreat.affected_targets.map((url, idx) => (
|
| 565 |
+
<span key={idx} className="bg-surface-container border border-outline-variant/80 text-on-surface font-mono text-[12px] px-3 py-1.5 rounded-lg flex items-center gap-2 font-medium">
|
| 566 |
+
<span className="w-2 h-2 rounded-full bg-red-500 animate-pulse"></span>
|
| 567 |
+
{url}
|
| 568 |
+
</span>
|
| 569 |
+
))}
|
| 570 |
+
</div>
|
| 571 |
+
</div>
|
| 572 |
+
)}
|
| 573 |
+
</div>
|
| 574 |
+
|
| 575 |
+
{/* Modal Actions Footer */}
|
| 576 |
+
<div className="p-4 bg-surface-container-lowest border-t border-outline-variant flex items-center justify-between flex-wrap gap-3">
|
| 577 |
+
<button
|
| 578 |
+
onClick={() => {
|
| 579 |
+
const query = selectedThreat.title;
|
| 580 |
+
setSelectedThreat(null);
|
| 581 |
+
openFullLogsView(query);
|
| 582 |
+
}}
|
| 583 |
+
className="px-4 py-2.5 bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-xl font-bold text-[13px] flex items-center gap-2 cursor-pointer transition-colors"
|
| 584 |
+
>
|
| 585 |
+
<Search className="w-4 h-4" />
|
| 586 |
+
Filter Audit Logs for this Threat
|
| 587 |
+
</button>
|
| 588 |
+
|
| 589 |
+
<button
|
| 590 |
+
onClick={() => setSelectedThreat(null)}
|
| 591 |
+
className="px-6 py-2.5 bg-primary text-white hover:brightness-110 rounded-xl font-bold text-[13px] cursor-pointer border-0 shadow-md shadow-primary/20 transition-all"
|
| 592 |
+
>
|
| 593 |
+
Close Window
|
| 594 |
+
</button>
|
| 595 |
+
</div>
|
| 596 |
+
</div>
|
| 597 |
+
</div>
|
| 598 |
+
);
|
| 599 |
+
};
|
| 600 |
+
|
| 601 |
// Full Page Threat Intelligence View Mode
|
| 602 |
if (isFullThreatsView) {
|
| 603 |
return (
|
|
|
|
| 827 |
return (
|
| 828 |
<tr
|
| 829 |
key={i}
|
| 830 |
+
className="hover:bg-surface-container-high/60 transition-colors group"
|
|
|
|
| 831 |
>
|
| 832 |
<td className="p-3.5 text-center font-extrabold text-[12px] text-error">
|
| 833 |
{rowIdx}
|
|
|
|
| 944 |
</>
|
| 945 |
)}
|
| 946 |
</div>
|
| 947 |
+
{selectedThreat && renderThreatModal()}
|
| 948 |
</div>
|
| 949 |
);
|
| 950 |
}
|
|
|
|
| 951 |
// Full Page Audit Logs Mode
|
| 952 |
if (isFullLogsView) {
|
| 953 |
return (
|
|
|
|
| 1162 |
</>
|
| 1163 |
)}
|
| 1164 |
</div>
|
| 1165 |
+
{selectedThreat && renderThreatModal()}
|
| 1166 |
</div>
|
| 1167 |
);
|
| 1168 |
}
|
|
|
|
| 1213 |
return (
|
| 1214 |
<li
|
| 1215 |
key={i}
|
| 1216 |
+
className="py-3 px-3 rounded-xl flex flex-col sm:flex-row sm:items-center justify-between gap-3 hover:bg-surface-container-high/40 transition-all group my-1"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1217 |
>
|
| 1218 |
<div className="flex items-start gap-3 pr-2">
|
| 1219 |
<span className="w-7 h-7 rounded-full bg-error/10 text-error flex items-center justify-center text-[12px] font-extrabold shrink-0 mt-0.5 border border-error/20">
|
|
|
|
| 1358 |
</div>
|
| 1359 |
</div>
|
| 1360 |
|
| 1361 |
+
{/* Global Threat Detail Modal */}
|
| 1362 |
+
{selectedThreat && renderThreatModal()}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1363 |
</div>
|
| 1364 |
);
|
| 1365 |
};
|