larxius commited on
Commit
478ddbf
·
verified ·
1 Parent(s): 7e81b70

Update frontend/src/pages/LogsAndThreats.jsx

Browse files
Files changed (1) hide show
  1. frontend/src/pages/LogsAndThreats.jsx +106 -43
frontend/src/pages/LogsAndThreats.jsx CHANGED
@@ -3,7 +3,8 @@ import { Link } from 'react-router-dom';
3
  import { useAuth } from '../components/AuthContext';
4
  import {
5
  ShieldAlert, Search, Download, RefreshCw, List, ArrowLeft, Filter,
6
- Info, X, ExternalLink, Shield, AlertTriangle, CheckCircle, Copy, Check, Terminal, Layers, Eye
 
7
  } from 'lucide-react';
8
 
9
  const THREAT_KNOWLEDGE_BASE = {
@@ -73,6 +74,7 @@ const LogsAndThreats = () => {
73
  // Selected Threat Detail Modal State
74
  const [selectedThreat, setSelectedThreat] = useState(null);
75
  const [copiedCode, setCopiedCode] = useState(false);
 
76
 
77
  // Full Page Threat Intelligence View State
78
  const [isFullThreatsView, setIsFullThreatsView] = useState(false);
@@ -201,6 +203,33 @@ const LogsAndThreats = () => {
201
  setThreatSortDir('desc');
202
  };
203
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  const copyToClipboard = (text) => {
205
  navigator.clipboard.writeText(text);
206
  setCopiedCode(true);
@@ -220,14 +249,20 @@ const LogsAndThreats = () => {
220
  );
221
  const kb = (kbKey ? THREAT_KNOWLEDGE_BASE[kbKey] : null) || {};
222
 
 
 
 
 
223
  return {
224
  title: titleKey || kbKey || 'Security Vulnerability',
225
  count: t.count || 1,
226
- severity: t.severity || kb.severity || 'Medium',
227
  category: t.category || kb.category || 'Security Headers',
228
  cvss: t.cvss_score || t.cvss || kb.cvss || 5.3,
229
  owasp: t.owasp_category || t.owasp || kb.owasp || 'A05:2021 - Security Misconfiguration',
230
- cwe: t.cwe_ids && t.cwe_ids.length ? t.cwe_ids : (kb.cwe || ['CWE-693']),
 
 
231
  description: t.description && t.description.length > 20 ? t.description : (kb.description || `Security intelligence scan detected "${titleKey}" across active system endpoints.`),
232
  impact: t.impact || kb.impact || 'Unpatched or missing security settings increase risk of exploitation, unauthorized data access, or service disruption.',
233
  remediation: t.remediation && t.remediation.length > 20 ? t.remediation : (kb.remediation || 'add_header Cross-Origin-Embedder-Policy "require-corp" always;'),
@@ -511,17 +546,24 @@ const LogsAndThreats = () => {
511
  <X className="w-5 h-5" />
512
  </button>
513
 
514
- <div className="flex items-center gap-2.5 flex-wrap mb-2 pr-10">
515
- <span className={`px-3 py-1 rounded-md text-[11px] font-black uppercase tracking-wider border flex items-center gap-1.5 ${getSeverityBadgeClass(selectedThreat.severity)}`}>
516
  <ShieldAlert className="w-3.5 h-3.5" />
517
  {selectedThreat.severity} SEVERITY
518
  </span>
519
- <span className="bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black px-3 py-1 rounded-md border border-cyan-500/30 font-mono">
520
  CVSS {selectedThreat.cvss}
521
  </span>
522
- <span className="bg-red-500/10 text-red-600 dark:text-red-400 text-[11px] font-black px-3 py-1 rounded-md border border-red-500/30 flex items-center gap-1.5">
523
- <span className="w-2 h-2 rounded-full bg-red-500 animate-pulse"></span>
524
- {selectedThreat.count} Detections Recorded
 
 
 
 
 
 
 
525
  </span>
526
  </div>
527
 
@@ -533,45 +575,55 @@ const LogsAndThreats = () => {
533
  {/* Modal Body: Spacious Executive View (Zero Scrollbar) */}
534
  <div className="p-4 sm:p-5 px-5 sm:px-6 space-y-3.5 text-sm bg-surface overflow-hidden">
535
 
536
- {/* Top Row: Category & OWASP Standard Badges */}
537
- <div className="grid grid-cols-1 sm:grid-cols-2 gap-3.5">
538
- <div className="bg-surface-container-lowest p-3 px-4 rounded-xl border border-outline-variant/60 flex items-center gap-3">
539
- <div className="w-8 h-8 rounded-lg bg-primary/10 text-primary flex items-center justify-center shrink-0">
540
- <Layers className="w-4 h-4" />
541
  </div>
542
  <div className="truncate">
543
- <span className="text-[10.5px] font-bold text-on-surface-variant uppercase tracking-wider block leading-none mb-1">Vulnerability Category</span>
544
- <span className="font-bold text-on-surface text-sm truncate block">{selectedThreat.category}</span>
545
  </div>
546
  </div>
547
 
548
- <div className="bg-surface-container-lowest p-3 px-4 rounded-xl border border-outline-variant/60 flex items-center gap-3">
549
- <div className="w-8 h-8 rounded-lg bg-indigo-500/10 text-indigo-500 flex items-center justify-center shrink-0">
550
- <Shield className="w-4 h-4" />
551
  </div>
552
  <div className="truncate">
553
- <span className="text-[10.5px] font-bold text-on-surface-variant uppercase tracking-wider block leading-none mb-1">OWASP Standard</span>
554
- <span className="font-bold text-indigo-500 text-sm truncate block">{selectedThreat.owasp}</span>
 
 
 
 
 
 
 
 
 
 
555
  </div>
556
  </div>
557
  </div>
558
 
559
  {/* Middle Grid: Threat Overview & Exploitation Risk */}
560
  <div className="grid grid-cols-1 sm:grid-cols-2 gap-3.5">
561
- <div className="bg-surface-container-lowest p-3.5 px-4 rounded-xl border-l-4 border-l-primary border border-outline-variant/60">
562
- <h3 className="font-bold text-on-surface text-sm mb-1.5 flex items-center gap-2">
563
- <Shield className="w-4 h-4 text-primary" /> Threat Overview
564
  </h3>
565
- <p className="text-on-surface-variant leading-relaxed text-[12.5px] sm:text-[13px] line-clamp-3">
566
  {selectedThreat.description}
567
  </p>
568
  </div>
569
 
570
- <div className="bg-surface-container-lowest p-3.5 px-4 rounded-xl border-l-4 border-l-amber-500 border border-outline-variant/60">
571
- <h3 className="font-bold text-amber-600 dark:text-amber-400 text-sm mb-1.5 flex items-center gap-2">
572
- <AlertTriangle className="w-4 h-4" /> Exploitation & Impact Risk
573
  </h3>
574
- <p className="text-on-surface-variant leading-relaxed text-[12.5px] sm:text-[13px] line-clamp-3">
575
  {selectedThreat.impact}
576
  </p>
577
  </div>
@@ -593,32 +645,32 @@ const LogsAndThreats = () => {
593
  </button>
594
  </div>
595
 
596
- <div className="bg-[#090d16] text-[#38bdf8] font-mono text-[12px] p-3 leading-relaxed whitespace-pre-wrap max-h-20 overflow-hidden">
597
  {selectedThreat.remediation}
598
  </div>
599
  </div>
600
 
601
  {/* Affected Target Endpoints */}
602
  {selectedThreat.affected_targets && selectedThreat.affected_targets.length > 0 && (
603
- <div className="bg-surface-container-lowest p-3 px-4 rounded-xl border border-outline-variant/60">
604
- <h3 className="font-bold text-on-surface text-xs mb-1.5 flex items-center gap-2">
605
  <ExternalLink className="w-3.5 h-3.5 text-primary" /> Affected Target Endpoints ({selectedThreat.affected_targets.length})
606
  </h3>
607
- <div className="flex flex-wrap gap-2">
608
  {selectedThreat.affected_targets.slice(0, 4).map((url, idx) => (
609
  <a
610
  key={idx}
611
  href={url}
612
  target="_blank"
613
  rel="noopener noreferrer"
614
- className="bg-surface-container border border-outline-variant/70 hover:border-primary text-on-surface font-mono text-xs px-2.5 py-1 rounded-md flex items-center gap-1.5 transition-all"
615
  >
616
  <span className="w-1.5 h-1.5 rounded-full bg-red-500"></span>
617
  {url}
618
  </a>
619
  ))}
620
  {selectedThreat.affected_targets.length > 4 && (
621
- <span className="bg-surface-container text-on-surface-variant font-mono text-xs px-2.5 py-1 rounded-md font-bold">
622
  +{selectedThreat.affected_targets.length - 4} more
623
  </span>
624
  )}
@@ -628,25 +680,36 @@ const LogsAndThreats = () => {
628
  </div>
629
 
630
  {/* Actions Footer */}
631
- <div className="p-3.5 px-5 sm:px-6 bg-surface-container-lowest border-t border-outline-variant/70 flex items-center justify-between flex-wrap gap-3">
632
  <button
633
  onClick={() => {
634
  const query = selectedThreat.title;
635
  setSelectedThreat(null);
636
  openFullLogsView(query);
637
  }}
638
- className="px-4 py-2 bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-xl font-bold text-xs sm:text-sm flex items-center gap-2 cursor-pointer transition-all active:scale-95"
639
  >
640
  <Search className="w-4 h-4" />
641
  Filter Audit Logs for this Threat
642
  </button>
643
 
644
- <button
645
- onClick={() => setSelectedThreat(null)}
646
- className="px-6 py-2 bg-primary text-white hover:brightness-110 rounded-xl font-bold text-xs sm:text-sm cursor-pointer border-0 shadow-md shadow-primary/20 transition-all active:scale-95"
647
- >
648
- Close Diagnostic Window
649
- </button>
 
 
 
 
 
 
 
 
 
 
 
650
  </div>
651
  </div>
652
  </div>
 
3
  import { useAuth } from '../components/AuthContext';
4
  import {
5
  ShieldAlert, Search, Download, RefreshCw, List, ArrowLeft, Filter,
6
+ Info, X, ExternalLink, Shield, AlertTriangle, CheckCircle, Copy, Check, Terminal, Layers, Eye,
7
+ Clock, Radio, FileText
8
  } from 'lucide-react';
9
 
10
  const THREAT_KNOWLEDGE_BASE = {
 
74
  // Selected Threat Detail Modal State
75
  const [selectedThreat, setSelectedThreat] = useState(null);
76
  const [copiedCode, setCopiedCode] = useState(false);
77
+ const [copiedBrief, setCopiedBrief] = useState(false);
78
 
79
  // Full Page Threat Intelligence View State
80
  const [isFullThreatsView, setIsFullThreatsView] = useState(false);
 
203
  setThreatSortDir('desc');
204
  };
205
 
206
+ const copyBriefToClipboard = (threat) => {
207
+ if (!threat) return;
208
+ const text = `[LARSHIELD EXECUTIVE THREAT BRIEF]
209
+ Threat Title: ${threat.title}
210
+ Severity: ${threat.severity} | CVSS Score: ${threat.cvss} | Detections: ${threat.count}
211
+ CWE Standard: ${threat.cwe} | Remediation SLA: ${threat.sla}
212
+ Category: ${threat.category}
213
+ OWASP Standard: ${threat.owasp}
214
+ Attack Vector: ${threat.attackVector}
215
+
216
+ THREAT OVERVIEW:
217
+ ${threat.description}
218
+
219
+ EXPLOITATION & IMPACT RISK:
220
+ ${threat.impact}
221
+
222
+ RECOMMENDED SECURITY FIX:
223
+ ${threat.remediation}
224
+
225
+ AFFECTED TARGET ENDPOINTS (${threat.affected_targets.length}):
226
+ ${threat.affected_targets.join('\n')}`;
227
+
228
+ navigator.clipboard.writeText(text);
229
+ setCopiedBrief(true);
230
+ setTimeout(() => setCopiedBrief(false), 2000);
231
+ };
232
+
233
  const copyToClipboard = (text) => {
234
  navigator.clipboard.writeText(text);
235
  setCopiedCode(true);
 
249
  );
250
  const kb = (kbKey ? THREAT_KNOWLEDGE_BASE[kbKey] : null) || {};
251
 
252
+ const sev = t.severity || kb.severity || 'Medium';
253
+ const isUrgent = sev.toLowerCase() === 'critical' || sev.toLowerCase() === 'high';
254
+ const rawCwe = t.cwe_ids && t.cwe_ids.length ? (Array.isArray(t.cwe_ids) ? t.cwe_ids[0] : t.cwe_ids) : (kb.cwe ? (Array.isArray(kb.cwe) ? kb.cwe[0] : kb.cwe) : 'CWE-693');
255
+
256
  return {
257
  title: titleKey || kbKey || 'Security Vulnerability',
258
  count: t.count || 1,
259
+ severity: sev,
260
  category: t.category || kb.category || 'Security Headers',
261
  cvss: t.cvss_score || t.cvss || kb.cvss || 5.3,
262
  owasp: t.owasp_category || t.owasp || kb.owasp || 'A05:2021 - Security Misconfiguration',
263
+ cwe: rawCwe,
264
+ sla: isUrgent ? 'Fix Required: Within 24 Hours' : 'Fix Required: Within 7 Days',
265
+ attackVector: kb.attack_vector || (titleKey.toLowerCase().includes('cve') || titleKey.toLowerCase().includes('tls') ? 'Network / Remote Exploitable' : 'HTTP Header Misconfiguration'),
266
  description: t.description && t.description.length > 20 ? t.description : (kb.description || `Security intelligence scan detected "${titleKey}" across active system endpoints.`),
267
  impact: t.impact || kb.impact || 'Unpatched or missing security settings increase risk of exploitation, unauthorized data access, or service disruption.',
268
  remediation: t.remediation && t.remediation.length > 20 ? t.remediation : (kb.remediation || 'add_header Cross-Origin-Embedder-Policy "require-corp" always;'),
 
546
  <X className="w-5 h-5" />
547
  </button>
548
 
549
+ <div className="flex items-center gap-2 flex-wrap mb-2 pr-10">
550
+ <span className={`px-2.5 py-0.5 rounded-md text-[11px] font-black uppercase tracking-wider border flex items-center gap-1 ${getSeverityBadgeClass(selectedThreat.severity)}`}>
551
  <ShieldAlert className="w-3.5 h-3.5" />
552
  {selectedThreat.severity} SEVERITY
553
  </span>
554
+ <span className="bg-cyan-500/10 text-cyan-600 dark:text-cyan-400 text-[11px] font-black px-2.5 py-0.5 rounded-md border border-cyan-500/30 font-mono">
555
  CVSS {selectedThreat.cvss}
556
  </span>
557
+ <span className="bg-purple-500/10 text-purple-600 dark:text-purple-400 text-[11px] font-black px-2.5 py-0.5 rounded-md border border-purple-500/30 font-mono">
558
+ {selectedThreat.cwe}
559
+ </span>
560
+ <span className="bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 text-[11px] font-black px-2.5 py-0.5 rounded-md border border-emerald-500/30 flex items-center gap-1">
561
+ <Clock className="w-3 h-3" />
562
+ {selectedThreat.sla}
563
+ </span>
564
+ <span className="bg-red-500/10 text-red-600 dark:text-red-400 text-[11px] font-black px-2.5 py-0.5 rounded-md border border-red-500/30 flex items-center gap-1">
565
+ <span className="w-1.5 h-1.5 rounded-full bg-red-500 animate-pulse"></span>
566
+ {selectedThreat.count} Detections
567
  </span>
568
  </div>
569
 
 
575
  {/* Modal Body: Spacious Executive View (Zero Scrollbar) */}
576
  <div className="p-4 sm:p-5 px-5 sm:px-6 space-y-3.5 text-sm bg-surface overflow-hidden">
577
 
578
+ {/* Top Row: Category, OWASP Standard & Attack Vector Badges */}
579
+ <div className="grid grid-cols-1 sm:grid-cols-3 gap-3">
580
+ <div className="bg-surface-container-lowest p-2.5 px-3 rounded-xl border border-outline-variant/60 flex items-center gap-2.5">
581
+ <div className="w-7 h-7 rounded-lg bg-primary/10 text-primary flex items-center justify-center shrink-0">
582
+ <Layers className="w-3.5 h-3.5" />
583
  </div>
584
  <div className="truncate">
585
+ <span className="text-[9.5px] font-bold text-on-surface-variant uppercase tracking-wider block leading-none mb-0.5">Category</span>
586
+ <span className="font-bold text-on-surface text-[12px] truncate block">{selectedThreat.category}</span>
587
  </div>
588
  </div>
589
 
590
+ <div className="bg-surface-container-lowest p-2.5 px-3 rounded-xl border border-outline-variant/60 flex items-center gap-2.5">
591
+ <div className="w-7 h-7 rounded-lg bg-indigo-500/10 text-indigo-500 flex items-center justify-center shrink-0">
592
+ <Shield className="w-3.5 h-3.5" />
593
  </div>
594
  <div className="truncate">
595
+ <span className="text-[9.5px] font-bold text-on-surface-variant uppercase tracking-wider block leading-none mb-0.5">OWASP Standard</span>
596
+ <span className="font-bold text-indigo-500 text-[12px] truncate block">{selectedThreat.owasp}</span>
597
+ </div>
598
+ </div>
599
+
600
+ <div className="bg-surface-container-lowest p-2.5 px-3 rounded-xl border border-outline-variant/60 flex items-center gap-2.5">
601
+ <div className="w-7 h-7 rounded-lg bg-rose-500/10 text-rose-500 flex items-center justify-center shrink-0">
602
+ <Radio className="w-3.5 h-3.5" />
603
+ </div>
604
+ <div className="truncate">
605
+ <span className="text-[9.5px] font-bold text-on-surface-variant uppercase tracking-wider block leading-none mb-0.5">Attack Vector</span>
606
+ <span className="font-bold text-rose-500 text-[12px] truncate block">{selectedThreat.attackVector}</span>
607
  </div>
608
  </div>
609
  </div>
610
 
611
  {/* Middle Grid: Threat Overview & Exploitation Risk */}
612
  <div className="grid grid-cols-1 sm:grid-cols-2 gap-3.5">
613
+ <div className="bg-surface-container-lowest p-3 px-3.5 rounded-xl border-l-4 border-l-primary border border-outline-variant/60">
614
+ <h3 className="font-bold text-on-surface text-xs mb-1 flex items-center gap-1.5">
615
+ <Shield className="w-3.5 h-3.5 text-primary" /> Threat Overview
616
  </h3>
617
+ <p className="text-on-surface-variant leading-relaxed text-[12px] line-clamp-3">
618
  {selectedThreat.description}
619
  </p>
620
  </div>
621
 
622
+ <div className="bg-surface-container-lowest p-3 px-3.5 rounded-xl border-l-4 border-l-amber-500 border border-outline-variant/60">
623
+ <h3 className="font-bold text-amber-600 dark:text-amber-400 text-xs mb-1 flex items-center gap-1.5">
624
+ <AlertTriangle className="w-3.5 h-3.5" /> Exploitation & Impact Risk
625
  </h3>
626
+ <p className="text-on-surface-variant leading-relaxed text-[12px] line-clamp-3">
627
  {selectedThreat.impact}
628
  </p>
629
  </div>
 
645
  </button>
646
  </div>
647
 
648
+ <div className="bg-[#090d16] text-[#38bdf8] font-mono text-[11.5px] p-2.5 leading-relaxed whitespace-pre-wrap max-h-16 overflow-hidden">
649
  {selectedThreat.remediation}
650
  </div>
651
  </div>
652
 
653
  {/* Affected Target Endpoints */}
654
  {selectedThreat.affected_targets && selectedThreat.affected_targets.length > 0 && (
655
+ <div className="bg-surface-container-lowest p-2.5 px-3.5 rounded-xl border border-outline-variant/60">
656
+ <h3 className="font-bold text-on-surface text-xs mb-1 flex items-center gap-1.5">
657
  <ExternalLink className="w-3.5 h-3.5 text-primary" /> Affected Target Endpoints ({selectedThreat.affected_targets.length})
658
  </h3>
659
+ <div className="flex flex-wrap gap-1.5">
660
  {selectedThreat.affected_targets.slice(0, 4).map((url, idx) => (
661
  <a
662
  key={idx}
663
  href={url}
664
  target="_blank"
665
  rel="noopener noreferrer"
666
+ className="bg-surface-container border border-outline-variant/70 hover:border-primary text-on-surface font-mono text-[11px] px-2 py-0.5 rounded-md flex items-center gap-1 transition-all"
667
  >
668
  <span className="w-1.5 h-1.5 rounded-full bg-red-500"></span>
669
  {url}
670
  </a>
671
  ))}
672
  {selectedThreat.affected_targets.length > 4 && (
673
+ <span className="bg-surface-container text-on-surface-variant font-mono text-[11px] px-2 py-0.5 rounded-md font-bold">
674
  +{selectedThreat.affected_targets.length - 4} more
675
  </span>
676
  )}
 
680
  </div>
681
 
682
  {/* Actions Footer */}
683
+ <div className="p-3 px-5 sm:px-6 bg-surface-container-lowest border-t border-outline-variant/70 flex items-center justify-between flex-wrap gap-2.5">
684
  <button
685
  onClick={() => {
686
  const query = selectedThreat.title;
687
  setSelectedThreat(null);
688
  openFullLogsView(query);
689
  }}
690
+ className="px-3.5 py-1.5 bg-primary/10 hover:bg-primary/20 text-primary border border-primary/30 rounded-xl font-bold text-xs sm:text-sm flex items-center gap-2 cursor-pointer transition-all active:scale-95"
691
  >
692
  <Search className="w-4 h-4" />
693
  Filter Audit Logs for this Threat
694
  </button>
695
 
696
+ <div className="flex items-center gap-2">
697
+ <button
698
+ onClick={() => copyBriefToClipboard(selectedThreat)}
699
+ className="px-3.5 py-1.5 bg-surface-container hover:bg-surface-container-highest text-on-surface rounded-xl font-bold text-xs sm:text-sm cursor-pointer border border-outline-variant/70 flex items-center gap-1.5 transition-all active:scale-95"
700
+ title="Copy Executive Threat Brief to Clipboard"
701
+ >
702
+ {copiedBrief ? <Check className="w-4 h-4 text-green-500" /> : <FileText className="w-4 h-4 text-primary" />}
703
+ {copiedBrief ? 'Brief Copied!' : 'Copy Threat Brief'}
704
+ </button>
705
+
706
+ <button
707
+ onClick={() => setSelectedThreat(null)}
708
+ className="px-5 py-1.5 bg-primary text-white hover:brightness-110 rounded-xl font-bold text-xs sm:text-sm cursor-pointer border-0 shadow-md shadow-primary/20 transition-all active:scale-95"
709
+ >
710
+ Close Window
711
+ </button>
712
+ </div>
713
  </div>
714
  </div>
715
  </div>