@threatcaptain/tc-reports 0.2.15 → 0.2.17

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.
package/dist/index.cjs CHANGED
@@ -51154,8 +51154,8 @@ var RadarChart = generateCategoricalChart({
51154
51154
  });
51155
51155
  const ATTACK_STEPS = [
51156
51156
  {
51157
- id: "get-in",
51158
- name: "Step 1: Get In",
51157
+ stepId: "get-in",
51158
+ stepName: "Step 1: Get In",
51159
51159
  description: "Initial access and reconnaissance phase",
51160
51160
  tactics: [
51161
51161
  "Reconnaissance",
@@ -51167,24 +51167,24 @@ const ATTACK_STEPS = [
51167
51167
  // red
51168
51168
  },
51169
51169
  {
51170
- id: "sneak-around",
51171
- name: "Step 2: Sneak Around",
51170
+ stepId: "sneak-around",
51171
+ stepName: "Step 2: Sneak Around",
51172
51172
  description: "Discovery and movement within the network",
51173
51173
  tactics: ["Discovery", "Lateral Movement", "Defense Evasion"],
51174
51174
  color: "#f59e0b"
51175
51175
  // amber
51176
51176
  },
51177
51177
  {
51178
- id: "take-control",
51179
- name: "Step 3: Take Control",
51178
+ stepId: "take-control",
51179
+ stepName: "Step 3: Take Control",
51180
51180
  description: "Establishing persistence and escalating privileges",
51181
51181
  tactics: ["Privilege Escalation", "Persistence", "Credential Access"],
51182
51182
  color: "#8b5cf6"
51183
51183
  // violet
51184
51184
  },
51185
51185
  {
51186
- id: "stay-hidden",
51187
- name: "Step 4: Stay Hidden",
51186
+ stepId: "stay-hidden",
51187
+ stepName: "Step 4: Stay Hidden",
51188
51188
  description: "Maintaining access and achieving objectives",
51189
51189
  tactics: ["Command and Control", "Collection", "Exfiltration", "Impact"],
51190
51190
  color: "#06b6d4"
@@ -51360,47 +51360,501 @@ const MitreAttack = ({ breachData, overallLikelihood }) => {
51360
51360
  ] })
51361
51361
  ] });
51362
51362
  };
51363
- const groupTitles = {
51364
- basic: "Basic Controls (Implementation Group 1)",
51365
- foundational: "Foundational Controls (Implementation Group 2)",
51366
- organizational: "Organizational Controls (Implementation Group 3)"
51367
- };
51368
- const groupDescriptions = {
51369
- basic: "Must-have cybersecurity hygiene controls that should be implemented by all organizations (Controls 1-6).",
51370
- foundational: "Deeper technical safeguards for organizations with moderate cybersecurity programs (Controls 7-16).",
51371
- organizational: "Governance and process controls for mature organizations with dedicated security teams (Controls 17-18)."
51372
- };
51373
- const controlLevels = {
51374
- basic: [1, 2, 3, 4, 5, 6],
51375
- // IG1 - Basic hygiene controls
51376
- foundational: [7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
51377
- // IG2 - Deeper technical safeguards
51378
- organizational: [17, 18]
51379
- // IG3 - Governance and process controls
51380
- };
51381
- const serviceDescriptions = {
51382
- 1: "Maintain an up-to-date, automated inventory of all hardware assets across the client environment, with real-time discovery and change tracking.",
51383
- 2: "Discover and track all installed software, enforce approved application lists, and remove or remediate unauthorized or outdated software.",
51384
- 3: "Implement and manage data encryption, DLP policies, and secure backup processes to safeguard sensitive information in transit and at rest.",
51385
- 4: "Deploy, enforce, and audit standardized hardening baselines for operating systems and applications to eliminate insecure default settings.",
51386
- 5: "Provision, modify, and decommission user and service accounts, enforce password policies, and regularly review privileges.",
51387
- 6: "Configure and maintain least-privilege access, multi-factor authentication, and role-based permissions across systems and applications.",
51388
- 7: "Perform scheduled vulnerability scans, prioritize detected issues, and coordinate patching or mitigation workflows.",
51389
- 8: "Collect, centralize, and analyze system and security logs from endpoints, servers, and network devices for threat detection and compliance.",
51390
- 9: "Deploy and manage email filtering, anti-phishing measures, and web-content filtering to block malicious messages and sites.",
51391
- 10: "Install, configure, and monitor endpoint anti-malware/EDR solutions to detect, quarantine, and remediate malicious code.",
51392
- 11: "Design, implement, and test backup and restore procedures to ensure rapid recovery from data loss or ransomware events.",
51393
- 12: "Monitor, configure, and maintain routers, switches, and firewalls for performance, availability, and secure configurations.",
51394
- 13: "Deploy IDS/IPS or NDR solutions, continuously monitor network traffic for anomalies, and respond to potential intrusions.",
51395
- 14: "Provide ongoing phishing simulations, interactive training modules, and compliance reporting to educate end users.",
51396
- 15: "Assess, onboard, and continuously monitor the security posture of third-party vendors and partners.",
51397
- 16: "Conduct automated and manual code scans, secure code reviews, and application hardening to identify and fix vulnerabilities.",
51398
- 17: "Develop, test, and execute incident response playbooks, coordinate investigations, and manage post-incident reporting.",
51399
- 18: "Perform periodic internal and external penetration tests, simulate real-world attacks, and deliver detailed remediation guidance."
51363
+ const CIS_MITRE_MAPPING = {
51364
+ 1: {
51365
+ controlName: "Inventory & Control of Enterprise Assets",
51366
+ mitrePhases: [
51367
+ "Reconnaissance",
51368
+ "Initial Access",
51369
+ "Defense Evasion",
51370
+ "Discovery"
51371
+ ],
51372
+ impactReduction: 15,
51373
+ // 15% reduction in breach cost
51374
+ implementationCost: 25e3,
51375
+ description: "Asset visibility prevents unknown attack vectors and reconnaissance"
51376
+ },
51377
+ 2: {
51378
+ controlName: "Inventory & Control of Software Assets",
51379
+ mitrePhases: ["Initial Access", "Execution", "Persistence", "Discovery"],
51380
+ impactReduction: 18,
51381
+ implementationCost: 3e4,
51382
+ description: "Software control blocks malicious applications"
51383
+ },
51384
+ 3: {
51385
+ controlName: "Data Protection",
51386
+ mitrePhases: ["Collection", "Exfiltration"],
51387
+ impactReduction: 35,
51388
+ implementationCost: 5e4,
51389
+ description: "Encryption dramatically reduces data breach impact"
51390
+ },
51391
+ 4: {
51392
+ controlName: "Secure Configuration of Enterprise Assets & Software",
51393
+ mitrePhases: ["Initial Access", "Privilege Escalation", "Defense Evasion"],
51394
+ impactReduction: 22,
51395
+ implementationCost: 4e4,
51396
+ description: "Hardening prevents exploitation of misconfigurations"
51397
+ },
51398
+ 5: {
51399
+ controlName: "Account Management",
51400
+ mitrePhases: [
51401
+ "Initial Access",
51402
+ "Privilege Escalation",
51403
+ "Persistence",
51404
+ "Credential Access"
51405
+ ],
51406
+ impactReduction: 28,
51407
+ implementationCost: 35e3,
51408
+ description: "Proper account controls limit attacker access"
51409
+ },
51410
+ 6: {
51411
+ controlName: "Access Control Management",
51412
+ mitrePhases: [
51413
+ "Initial Access",
51414
+ "Privilege Escalation",
51415
+ "Lateral Movement",
51416
+ "Credential Access"
51417
+ ],
51418
+ impactReduction: 30,
51419
+ implementationCost: 45e3,
51420
+ description: "MFA and access controls significantly reduce breach success"
51421
+ },
51422
+ 7: {
51423
+ controlName: "Continuous Vulnerability Management",
51424
+ mitrePhases: [
51425
+ "Resource Development",
51426
+ "Initial Access",
51427
+ "Privilege Escalation",
51428
+ "Defense Evasion",
51429
+ "Discovery"
51430
+ ],
51431
+ impactReduction: 25,
51432
+ implementationCost: 6e4,
51433
+ description: "Patching closes known attack vectors and limits resource development"
51434
+ },
51435
+ 8: {
51436
+ controlName: "Audit Log Management",
51437
+ mitrePhases: ["Defense Evasion", "Collection", "Discovery"],
51438
+ impactReduction: 20,
51439
+ implementationCost: 55e3,
51440
+ description: "Logging enables faster detection and response"
51441
+ },
51442
+ 9: {
51443
+ controlName: "Email & Web Browser Protections",
51444
+ mitrePhases: [
51445
+ "Resource Development",
51446
+ "Initial Access",
51447
+ "Command and Control"
51448
+ ],
51449
+ impactReduction: 32,
51450
+ implementationCost: 25e3,
51451
+ description: "Blocks most common attack vectors and resource development"
51452
+ },
51453
+ 10: {
51454
+ controlName: "Malware Defenses",
51455
+ mitrePhases: ["Initial Access", "Execution", "Defense Evasion"],
51456
+ impactReduction: 28,
51457
+ implementationCost: 4e4,
51458
+ description: "EDR prevents malware execution and lateral movement"
51459
+ },
51460
+ 11: {
51461
+ controlName: "Data Recovery",
51462
+ mitrePhases: ["Impact"],
51463
+ impactReduction: 45,
51464
+ implementationCost: 35e3,
51465
+ description: "Backups dramatically reduce ransomware impact"
51466
+ },
51467
+ 12: {
51468
+ controlName: "Network Infrastructure Management",
51469
+ mitrePhases: [
51470
+ "Initial Access",
51471
+ "Lateral Movement",
51472
+ "Command and Control",
51473
+ "Discovery"
51474
+ ],
51475
+ impactReduction: 18,
51476
+ implementationCost: 5e4,
51477
+ description: "Network segmentation limits breach scope"
51478
+ },
51479
+ 13: {
51480
+ controlName: "Network Monitoring & Defense",
51481
+ mitrePhases: [
51482
+ "Reconnaissance",
51483
+ "Initial Access",
51484
+ "Lateral Movement",
51485
+ "Command and Control",
51486
+ "Exfiltration",
51487
+ "Discovery"
51488
+ ],
51489
+ impactReduction: 25,
51490
+ implementationCost: 7e4,
51491
+ description: "Network detection identifies threats early including reconnaissance"
51492
+ },
51493
+ 14: {
51494
+ controlName: "Security Awareness & Skills Training",
51495
+ mitrePhases: ["Initial Access", "Credential Access"],
51496
+ impactReduction: 40,
51497
+ implementationCost: 15e3,
51498
+ description: "Training prevents human error attacks"
51499
+ },
51500
+ 15: {
51501
+ controlName: "Service Provider Management",
51502
+ mitrePhases: ["Resource Development", "Initial Access"],
51503
+ impactReduction: 12,
51504
+ implementationCost: 2e4,
51505
+ description: "Third-party risk management reduces supply chain attacks"
51506
+ },
51507
+ 16: {
51508
+ controlName: "Application Software Security",
51509
+ mitrePhases: ["Initial Access", "Execution"],
51510
+ impactReduction: 20,
51511
+ implementationCost: 8e4,
51512
+ description: "Secure coding prevents application-based attacks"
51513
+ },
51514
+ 17: {
51515
+ controlName: "Incident Response Management",
51516
+ mitrePhases: ["Impact"],
51517
+ impactReduction: 30,
51518
+ implementationCost: 45e3,
51519
+ description: "Faster response reduces breach duration and cost"
51520
+ },
51521
+ 18: {
51522
+ controlName: "Penetration Testing",
51523
+ mitrePhases: ["Reconnaissance", "Discovery"],
51524
+ impactReduction: 15,
51525
+ implementationCost: 25e3,
51526
+ description: "Testing identifies vulnerabilities before attackers through controlled reconnaissance"
51527
+ }
51528
+ };
51529
+ const MITRE_DESCRIPTIONS = {
51530
+ "Reconnaissance": "Gathering information to plan future adversary operations, that can be conducted against the target of interest.",
51531
+ "Resource Development": "Establishing resources they can use to support operations during their campaign targeting an organization.",
51532
+ "Initial Access": "Trying to get into your network through various entry points like spear phishing emails or exploiting public applications.",
51533
+ "Execution": "Running malicious code on local or remote systems to achieve their objectives.",
51534
+ "Persistence": "Maintaining their foothold in your systems by surviving reboots, changed credentials, and other interruptions.",
51535
+ "Privilege Escalation": "Gaining higher-level permissions to access more resources and sensitive information.",
51536
+ "Defense Evasion": "Avoiding detection by disabling security tools, obfuscating content, or hiding artifacts.",
51537
+ "Credential Access": "Stealing account names and passwords to gain access to systems and data.",
51538
+ "Discovery": "Learning about your environment and internal network to understand what they control and benefits their goals.",
51539
+ "Lateral Movement": "Moving through your environment to reach their objective, often accessing remote systems.",
51540
+ "Collection": "Gathering information and files that are of interest to their goal and objectives.",
51541
+ "Command and Control": "Communicating with compromised systems to control them and exfiltrate data.",
51542
+ "Exfiltration": "Stealing data from your network, often over their command and control channel.",
51543
+ "Impact": "Manipulating, interrupting, or destroying your systems and data to achieve their goals."
51544
+ };
51545
+ const SelectedTacticDetails = ({
51546
+ selectedTactic,
51547
+ breachData,
51548
+ onClose
51549
+ }) => {
51550
+ const selectedPhase = breachData.mitrePhases.find(
51551
+ (p2) => p2.phase === selectedTactic
51552
+ );
51553
+ if (!selectedPhase) return null;
51554
+ const getRiskLevelColor2 = (riskLevel) => {
51555
+ switch (riskLevel) {
51556
+ case "low":
51557
+ return "#10b981";
51558
+ case "medium":
51559
+ return "#f59e0b";
51560
+ case "high":
51561
+ return "#ef4444";
51562
+ default:
51563
+ return "#6b7280";
51564
+ }
51565
+ };
51566
+ const relevantCISControls = Object.entries(CIS_MITRE_MAPPING).filter(([_, mapping]) => mapping.mitrePhases.includes(selectedTactic)).map(([controlNumber, mapping]) => {
51567
+ const controlNum = parseInt(controlNumber);
51568
+ const controlMapping = breachData.controlMappings.find(
51569
+ (c2) => c2.controlNumber === controlNum
51570
+ );
51571
+ return {
51572
+ controlNumber: controlNum,
51573
+ controlName: mapping.controlName,
51574
+ implemented: (controlMapping == null ? void 0 : controlMapping.implemented) || false,
51575
+ description: mapping.description
51576
+ };
51577
+ }).sort((a2, b) => a2.controlNumber - b.controlNumber);
51578
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 p-4 bg-white rounded-lg border relative", children: [
51579
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-start mb-3", children: [
51580
+ /* @__PURE__ */ jsxRuntime.jsx("h5", { className: "font-semibold text-gray-900", children: selectedPhase.phase }),
51581
+ /* @__PURE__ */ jsxRuntime.jsx(
51582
+ Button$1,
51583
+ {
51584
+ variant: "ghost",
51585
+ size: "sm",
51586
+ onClick: onClose,
51587
+ className: "h-6 w-6 p-0 hover:bg-gray-100",
51588
+ children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" })
51589
+ }
51590
+ )
51591
+ ] }),
51592
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mb-4", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-700", children: MITRE_DESCRIPTIONS[selectedPhase.phase] || "No description available for this tactic." }) }),
51593
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4 text-sm mb-4", children: [
51594
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
51595
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600", children: "Coverage:" }),
51596
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2 font-medium", children: [
51597
+ selectedPhase.coverage,
51598
+ "%"
51599
+ ] })
51600
+ ] }),
51601
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
51602
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600", children: "Risk Level:" }),
51603
+ /* @__PURE__ */ jsxRuntime.jsx(
51604
+ "span",
51605
+ {
51606
+ className: "ml-2 font-medium",
51607
+ style: { color: getRiskLevelColor2(selectedPhase.riskLevel) },
51608
+ children: selectedPhase.riskLevel.charAt(0).toUpperCase() + selectedPhase.riskLevel.slice(1)
51609
+ }
51610
+ )
51611
+ ] }),
51612
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
51613
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600", children: "Protection Status:" }),
51614
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 font-medium", children: selectedPhase.coverage >= 80 ? "Well Protected" : selectedPhase.coverage >= 50 ? "Partially Protected" : "Vulnerable" })
51615
+ ] })
51616
+ ] }),
51617
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t pt-4", children: [
51618
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2 mb-3", children: [
51619
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Shield, { className: "h-4 w-4 text-blue-600" }),
51620
+ /* @__PURE__ */ jsxRuntime.jsx("h6", { className: "font-medium text-gray-900", children: "CIS Controls That Improve This Tactic" })
51621
+ ] }),
51622
+ relevantCISControls.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: relevantCISControls.map((control) => /* @__PURE__ */ jsxRuntime.jsxs(
51623
+ "div",
51624
+ {
51625
+ className: `p-3 rounded-lg border ${control.implemented ? "bg-green-50 border-green-200" : "bg-orange-50 border-orange-200"}`,
51626
+ children: [
51627
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-start justify-between mb-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-2", children: [
51628
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "font-medium text-sm", children: [
51629
+ "CIS Control ",
51630
+ control.controlNumber
51631
+ ] }),
51632
+ /* @__PURE__ */ jsxRuntime.jsx(
51633
+ Badge,
51634
+ {
51635
+ variant: control.implemented ? "default" : "secondary",
51636
+ className: control.implemented ? "bg-green-100 text-green-800 border-green-200" : "bg-orange-100 text-orange-800 border-orange-200",
51637
+ children: control.implemented ? "Implemented" : "Not Implemented"
51638
+ }
51639
+ )
51640
+ ] }) }),
51641
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-medium text-gray-800 mb-1", children: control.controlName }),
51642
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-600", children: control.description })
51643
+ ]
51644
+ },
51645
+ control.controlNumber
51646
+ )) }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500 italic", children: "No CIS controls are mapped to this MITRE tactic." }),
51647
+ relevantCISControls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 p-2 bg-blue-50 rounded border border-blue-200", children: /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-blue-700", children: [
51648
+ /* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Coverage Calculation:" }),
51649
+ " This tactic's",
51650
+ " ",
51651
+ selectedPhase.coverage,
51652
+ "% coverage is based on",
51653
+ " ",
51654
+ relevantCISControls.filter((c2) => c2.implemented).length,
51655
+ " of",
51656
+ " ",
51657
+ relevantCISControls.length,
51658
+ " relevant CIS controls being implemented."
51659
+ ] }) })
51660
+ ] })
51661
+ ] });
51662
+ };
51663
+ const MITRETacticsOverview = ({
51664
+ breachData,
51665
+ selectedTactic,
51666
+ setSelectedTactic,
51667
+ onTacticClick
51668
+ }) => {
51669
+ var _a;
51670
+ const [selectedStep, setSelectedStep] = React.useState(null);
51671
+ const getRiskLevelColor2 = (riskLevel) => {
51672
+ switch (riskLevel) {
51673
+ case "low":
51674
+ return "#10b981";
51675
+ case "medium":
51676
+ return "#f59e0b";
51677
+ case "high":
51678
+ return "#ef4444";
51679
+ default:
51680
+ return "#6b7280";
51681
+ }
51682
+ };
51683
+ const handleClosePopup = () => {
51684
+ setSelectedTactic(null);
51685
+ };
51686
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-gray-50 p-4 rounded-lg", children: [
51687
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "font-medium text-sm mb-3", children: "MITRE ATT&CK Kill Chain Coverage - 4 Attack Steps" }),
51688
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-gray-500 mb-4", children: "Click on any step to explore individual tactics" }),
51689
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 md:grid-cols-2 xl:grid-cols-4 gap-4 mb-6", children: ATTACK_STEPS.map((step) => {
51690
+ var _a2;
51691
+ const stepData = (_a2 = breachData.attackSteps) == null ? void 0 : _a2.find(
51692
+ (s2) => s2.stepId === step.stepId
51693
+ );
51694
+ const coverage = (stepData == null ? void 0 : stepData.coverage) || 0;
51695
+ const riskLevel = (stepData == null ? void 0 : stepData.riskLevel) || "medium";
51696
+ return /* @__PURE__ */ jsxRuntime.jsxs(
51697
+ "div",
51698
+ {
51699
+ className: `bg-white p-3 rounded-lg border cursor-pointer transition-all duration-200 ${selectedStep === step.stepId ? "ring-2 ring-blue-300 shadow-md" : "hover:shadow-sm"}`,
51700
+ onClick: () => {
51701
+ setSelectedStep(
51702
+ selectedStep === step.stepId ? null : step.stepId
51703
+ );
51704
+ onTacticClick("");
51705
+ },
51706
+ onKeyDown: (e) => {
51707
+ if (e.key === "Enter" || e.key === " ") {
51708
+ e.preventDefault();
51709
+ setSelectedStep(
51710
+ selectedStep === step.stepId ? null : step.stepId
51711
+ );
51712
+ onTacticClick("");
51713
+ }
51714
+ },
51715
+ role: "button",
51716
+ tabIndex: 0,
51717
+ "aria-label": `${step.stepName}: ${step.description}`,
51718
+ children: [
51719
+ /* @__PURE__ */ jsxRuntime.jsx(
51720
+ "div",
51721
+ {
51722
+ className: "text-sm font-medium mb-1",
51723
+ style: { color: step.color },
51724
+ children: step.stepName
51725
+ }
51726
+ ),
51727
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-gray-600 mb-2", children: step.description }),
51728
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-2 bg-gray-200 rounded-full overflow-hidden mb-1", children: /* @__PURE__ */ jsxRuntime.jsx(
51729
+ "div",
51730
+ {
51731
+ className: "h-full transition-all duration-300",
51732
+ style: {
51733
+ width: `${coverage}%`,
51734
+ backgroundColor: step.color
51735
+ }
51736
+ }
51737
+ ) }),
51738
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between text-xs", children: [
51739
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-gray-600", children: [
51740
+ coverage,
51741
+ "% Coverage"
51742
+ ] }),
51743
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: getRiskLevelColor2(riskLevel) }, children: [
51744
+ riskLevel.charAt(0).toUpperCase() + riskLevel.slice(1),
51745
+ " Risk"
51746
+ ] })
51747
+ ] })
51748
+ ]
51749
+ },
51750
+ step.stepId
51751
+ );
51752
+ }) }),
51753
+ selectedStep && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
51754
+ /* @__PURE__ */ jsxRuntime.jsxs("h5", { className: "font-medium text-sm mb-3", children: [
51755
+ "Individual Tactics for",
51756
+ " ",
51757
+ (_a = ATTACK_STEPS.find((s2) => s2.stepId === selectedStep)) == null ? void 0 : _a.stepName,
51758
+ " ",
51759
+ "(Click to view details)"
51760
+ ] }),
51761
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-2", children: breachData.mitrePhases.filter((phase) => {
51762
+ const step = getTacticStep(phase.phase);
51763
+ return (step == null ? void 0 : step.stepId) === selectedStep;
51764
+ }).sort((a2, b) => {
51765
+ const stepA = getTacticStep(a2.phase);
51766
+ const stepB = getTacticStep(b.phase);
51767
+ const stepOrder = [
51768
+ "get-in",
51769
+ "sneak-around",
51770
+ "take-control",
51771
+ "stay-hidden"
51772
+ ];
51773
+ const indexA = stepA ? stepOrder.indexOf(stepA.stepId) : 999;
51774
+ const indexB = stepB ? stepOrder.indexOf(stepB.stepId) : 999;
51775
+ if (indexA !== indexB) {
51776
+ return indexA - indexB;
51777
+ }
51778
+ return a2.phase.localeCompare(b.phase);
51779
+ }).map((phase) => {
51780
+ const step = getTacticStep(phase.phase);
51781
+ return /* @__PURE__ */ jsxRuntime.jsxs(
51782
+ "div",
51783
+ {
51784
+ className: `text-center cursor-pointer transition-all duration-200 p-2 rounded border ${selectedTactic === phase.phase ? "bg-white shadow-md ring-2 ring-blue-300" : "hover:bg-white hover:shadow-sm"}`,
51785
+ onClick: () => onTacticClick(phase.phase),
51786
+ onKeyDown: (e) => {
51787
+ if (e.key === "Enter" || e.key === " ") {
51788
+ e.preventDefault();
51789
+ onTacticClick(phase.phase);
51790
+ }
51791
+ },
51792
+ role: "button",
51793
+ tabIndex: 0,
51794
+ "aria-label": phase.phase,
51795
+ children: [
51796
+ /* @__PURE__ */ jsxRuntime.jsx(
51797
+ "div",
51798
+ {
51799
+ className: "text-xs font-medium truncate mb-1",
51800
+ title: phase.phase,
51801
+ children: phase.phase
51802
+ }
51803
+ ),
51804
+ step && /* @__PURE__ */ jsxRuntime.jsx(
51805
+ "div",
51806
+ {
51807
+ className: "text-xs mb-1",
51808
+ style: { color: step.color },
51809
+ children: step.stepName.replace("Step ", "")
51810
+ }
51811
+ ),
51812
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full h-2 bg-gray-200 rounded-full overflow-hidden", children: /* @__PURE__ */ jsxRuntime.jsx(
51813
+ "div",
51814
+ {
51815
+ className: "h-full transition-all duration-300",
51816
+ style: {
51817
+ width: `${phase.coverage}%`,
51818
+ backgroundColor: (step == null ? void 0 : step.color) || getRiskLevelColor2(phase.riskLevel)
51819
+ }
51820
+ }
51821
+ ) }),
51822
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-gray-600 mt-1", children: [
51823
+ phase.coverage,
51824
+ "%"
51825
+ ] }),
51826
+ /* @__PURE__ */ jsxRuntime.jsxs(
51827
+ "div",
51828
+ {
51829
+ className: "text-xs mt-1",
51830
+ style: { color: getRiskLevelColor2(phase.riskLevel) },
51831
+ children: [
51832
+ phase.riskLevel.charAt(0).toUpperCase() + phase.riskLevel.slice(1),
51833
+ " ",
51834
+ "Risk"
51835
+ ]
51836
+ }
51837
+ )
51838
+ ]
51839
+ },
51840
+ phase.phase
51841
+ );
51842
+ }) })
51843
+ ] }),
51844
+ selectedTactic && /* @__PURE__ */ jsxRuntime.jsx(
51845
+ SelectedTacticDetails,
51846
+ {
51847
+ selectedTactic,
51848
+ breachData,
51849
+ onClose: handleClosePopup
51850
+ }
51851
+ )
51852
+ ] });
51400
51853
  };
51401
51854
  const BreachLikelihood = ({ reportData }) => {
51402
51855
  var _a;
51403
51856
  const { clientData, securityAssessment, breachData } = reportData;
51857
+ const [selectedTactic, setSelectedTactic] = React.useState(null);
51404
51858
  const calculateBreachLikelihood = (protectionLevel) => {
51405
51859
  if ((securityAssessment == null ? void 0 : securityAssessment.overall_breach_likelihood) !== null && (securityAssessment == null ? void 0 : securityAssessment.overall_breach_likelihood) !== void 0) {
51406
51860
  return Math.round(securityAssessment.overall_breach_likelihood);
@@ -51489,23 +51943,15 @@ const BreachLikelihood = ({ reportData }) => {
51489
51943
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-2xl font-bold text-slate-900 mb-2", children: "Understanding Your Numbers" }),
51490
51944
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-slate-600", children: "How We Calculate Your Risk" })
51491
51945
  ] }),
51492
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-6", children: Object.entries(groupTitles).map(([groupKey, title]) => /* @__PURE__ */ jsxRuntime.jsxs(React.Fragment, { children: [
51493
- /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-lg font-semibold mb-2", children: title }),
51494
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-4", children: groupDescriptions[groupKey] }),
51495
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "border border-slate-200 bg-slate-50 rounded-lg py-2 px-4 flex flex-col w-full", children: controlLevels[groupKey].map(
51496
- (control) => /* @__PURE__ */ jsxRuntime.jsxs(
51497
- "li",
51498
- {
51499
- className: "py-2 flex items-center w-full",
51500
- children: [
51501
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-h-6 max-w-6 w-full text-sm flex items-center justify-center rounded-full border bg-blue-100 border-blue-900 text-blue-900 font-bold mr-4", children: control }),
51502
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex leading-tight", children: serviceDescriptions[control] })
51503
- ]
51504
- },
51505
- control
51506
- )
51507
- ) }) })
51508
- ] }, groupKey)) }),
51946
+ /* @__PURE__ */ jsxRuntime.jsx(
51947
+ MITRETacticsOverview,
51948
+ {
51949
+ breachData,
51950
+ selectedTactic,
51951
+ setSelectedTactic,
51952
+ onTacticClick: setSelectedTactic
51953
+ }
51954
+ ),
51509
51955
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "bg-slate-50 rounded-lg p-6 mb-6", children: [
51510
51956
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-xl font-bold mb-4", children: "Our Approach" }),
51511
51957
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-slate-700", children: "We use the same data sources that insurance companies and security professionals rely on. Our calculations are conservative - real attack costs are often higher than our estimates." })
@@ -52381,6 +52827,89 @@ const InsuranceHealthGauge = ({
52381
52827
  ) })
52382
52828
  ] });
52383
52829
  };
52830
+ const InsuranceImpactCards = ({
52831
+ score
52832
+ }) => {
52833
+ const getCardClasses = (score2) => {
52834
+ if (score2 >= 775) return "bg-green-50 border-green-200";
52835
+ if (score2 >= 700) return "bg-green-50 border-green-300";
52836
+ if (score2 >= 625) return "bg-blue-50 border-blue-200";
52837
+ if (score2 >= 550) return "bg-yellow-50 border-yellow-200";
52838
+ if (score2 >= 450) return "bg-orange-50 border-orange-200";
52839
+ return "bg-red-50 border-red-200";
52840
+ };
52841
+ const getIconClasses = (score2) => {
52842
+ if (score2 >= 775) return "text-green-600";
52843
+ if (score2 >= 700) return "text-green-600";
52844
+ if (score2 >= 625) return "text-blue-600";
52845
+ if (score2 >= 550) return "text-yellow-600";
52846
+ if (score2 >= 450) return "text-orange-600";
52847
+ return "text-red-600";
52848
+ };
52849
+ const getTextClasses = (score2) => {
52850
+ if (score2 >= 775) return "text-green-900";
52851
+ if (score2 >= 700) return "text-green-900";
52852
+ if (score2 >= 625) return "text-blue-900";
52853
+ if (score2 >= 550) return "text-yellow-900";
52854
+ if (score2 >= 450) return "text-orange-900";
52855
+ return "text-red-900";
52856
+ };
52857
+ const getDescriptionClasses = (score2) => {
52858
+ if (score2 >= 775) return "text-green-700";
52859
+ if (score2 >= 700) return "text-green-700";
52860
+ if (score2 >= 625) return "text-blue-700";
52861
+ if (score2 >= 550) return "text-yellow-700";
52862
+ if (score2 >= 450) return "text-orange-700";
52863
+ return "text-red-700";
52864
+ };
52865
+ const getCoverageText = (score2) => {
52866
+ if (score2 >= 775) return "Premium coverage with enhanced terms";
52867
+ if (score2 >= 700) return "Comprehensive coverage options available";
52868
+ if (score2 >= 625) return "Good coverage with standard terms";
52869
+ if (score2 >= 550) return "Limited coverage options";
52870
+ if (score2 >= 450) return "Restricted coverage with exclusions";
52871
+ return "Minimal coverage, high exclusions";
52872
+ };
52873
+ const getPremiumText = (score2) => {
52874
+ if (score2 >= 775) return "Preferred rates with significant discounts";
52875
+ if (score2 >= 700) return "Competitive rates, potential discounts";
52876
+ if (score2 >= 625) return "Standard market rates";
52877
+ if (score2 >= 550) return "Above-average premiums";
52878
+ if (score2 >= 450) return "High premiums with surcharges";
52879
+ return "Very high premiums, difficult to place";
52880
+ };
52881
+ const getUnderwritingText = (score2) => {
52882
+ if (score2 >= 775) return "Fast-track approval, minimal documentation";
52883
+ if (score2 >= 700) return "Streamlined approval process";
52884
+ if (score2 >= 625) return "Standard review and approval";
52885
+ if (score2 >= 550) return "Extended review process";
52886
+ if (score2 >= 450) return "Detailed review, additional requirements";
52887
+ return "Extensive review, may require risk mitigation plan";
52888
+ };
52889
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-1 md:grid-cols-3 gap-4", children: [
52890
+ /* @__PURE__ */ jsxRuntime.jsx(Card, { className: getCardClasses(score), children: /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "pt-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3", children: [
52891
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Shield, { className: `h-5 w-5 mt-0.5 ${getIconClasses(score)}` }),
52892
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
52893
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `font-medium ${getTextClasses(score)}`, children: "Coverage Availability" }),
52894
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-sm mt-1 ${getDescriptionClasses(score)}`, children: getCoverageText(score) })
52895
+ ] })
52896
+ ] }) }) }),
52897
+ /* @__PURE__ */ jsxRuntime.jsx(Card, { className: getCardClasses(score), children: /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "pt-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3", children: [
52898
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.TrendingUp, { className: `h-5 w-5 mt-0.5 ${getIconClasses(score)}` }),
52899
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
52900
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `font-medium ${getTextClasses(score)}`, children: "Premium Impact" }),
52901
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-sm mt-1 ${getDescriptionClasses(score)}`, children: getPremiumText(score) })
52902
+ ] })
52903
+ ] }) }) }),
52904
+ /* @__PURE__ */ jsxRuntime.jsx(Card, { className: getCardClasses(score), children: /* @__PURE__ */ jsxRuntime.jsx(CardContent, { className: "pt-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-3", children: [
52905
+ /* @__PURE__ */ jsxRuntime.jsx(lucideReact.FileText, { className: `h-5 w-5 mt-0.5 ${getIconClasses(score)}` }),
52906
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
52907
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: `font-medium ${getTextClasses(score)}`, children: "Underwriting Process" }),
52908
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: `text-sm mt-1 ${getDescriptionClasses(score)}`, children: getUnderwritingText(score) })
52909
+ ] })
52910
+ ] }) }) })
52911
+ ] });
52912
+ };
52384
52913
  const InsuranceHealthScore = ({ reportData }) => {
52385
52914
  const { insuranceHealthData } = reportData;
52386
52915
  const score = insuranceHealthData.score || 650;
@@ -52409,7 +52938,7 @@ const InsuranceHealthScore = ({ reportData }) => {
52409
52938
  className: `rounded-lg p-6 text-white text-center ${scoreCategoryData.bgColor}`,
52410
52939
  children: [
52411
52940
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-center space-x-2 mb-2", children: [
52412
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-8 h-8 rounded-full bg-white/20 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: score }) }),
52941
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-12 h-12 p-2 rounded-full bg-white/20 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-lg font-bold", children: score }) }),
52413
52942
  /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-2xl font-bold", children: "INSURANCE HEALTH SCORE" })
52414
52943
  ] }),
52415
52944
  /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-4xl font-bold", children: `${score}/850` }),
@@ -52470,33 +52999,36 @@ const InsuranceHealthScore = ({ reportData }) => {
52470
52999
  insuranceHealthData.responses
52471
53000
  );
52472
53001
  return domains.map((domain, index2) => {
52473
- let statusPill = "";
52474
53002
  let statusClass = "";
52475
53003
  const percentage = domain.percentage || 0;
52476
53004
  if (percentage === 0) {
52477
- statusPill = "FAIL";
52478
- statusClass = "bg-red-500 text-white";
53005
+ statusClass = "bg-red-500";
52479
53006
  } else if (percentage === 100) {
52480
- statusPill = "PASS";
52481
- statusClass = "bg-green-500 text-white";
53007
+ statusClass = "bg-green-500";
52482
53008
  } else {
52483
- statusPill = "NEEDS IMPROVEMENT";
52484
- statusClass = "bg-yellow-600 text-white";
53009
+ statusClass = "bg-yellow-600";
52485
53010
  }
52486
- return /* @__PURE__ */ jsxRuntime.jsx(
53011
+ return /* @__PURE__ */ jsxRuntime.jsxs(
52487
53012
  "div",
52488
53013
  {
52489
53014
  className: "bg-white border border-slate-200 rounded-lg p-4",
52490
- children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between items-center", children: [
52491
- /* @__PURE__ */ jsxRuntime.jsx("h5", { className: "font-medium text-slate-900 text-sm", children: domain.name }),
52492
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsx(
52493
- "span",
53015
+ children: [
53016
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-between mb-1 text-sm", children: [
53017
+ /* @__PURE__ */ jsxRuntime.jsx("h5", { className: "font-medium text-slate-900", children: domain.name }),
53018
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-gray-400", children: [
53019
+ domain.score,
53020
+ "/",
53021
+ domain.maxScore
53022
+ ] })
53023
+ ] }),
53024
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-full bg-gray-200 rounded-full h-3", children: /* @__PURE__ */ jsxRuntime.jsx(
53025
+ "div",
52494
53026
  {
52495
- className: `inline-block px-3 py-1 rounded-full text-xs font-semibold uppercase tracking-wider ${statusClass}`,
52496
- children: statusPill
53027
+ className: `h-4 rounded-full transition-all duration-500 ${statusClass}`,
53028
+ style: { width: percentage + "%" }
52497
53029
  }
52498
53030
  ) })
52499
- ] })
53031
+ ]
52500
53032
  },
52501
53033
  index2
52502
53034
  );
@@ -52506,7 +53038,8 @@ const InsuranceHealthScore = ({ reportData }) => {
52506
53038
  }
52507
53039
  })() })
52508
53040
  ] })
52509
- ] })
53041
+ ] }),
53042
+ /* @__PURE__ */ jsxRuntime.jsx(InsuranceImpactCards, { score })
52510
53043
  ] }),
52511
53044
  /* @__PURE__ */ jsxRuntime.jsxs("section", { className: "report-page space-y-6 border-t border-slate-200 pt-8", children: [
52512
53045
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [