From 21c6febd22ac8f2594af822e6ffc1f2f5bc86f64 Mon Sep 17 00:00:00 2001 From: kitos Date: Tue, 7 Jul 2026 16:30:27 +0200 Subject: [PATCH] fix(frontend): render markdown descriptions properly, fix tooltip/banner wording MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Wrap 8 previously-raw description fields in MarkdownText so imported markdown (links, bold, lists, MITRE citations) renders instead of showing literal syntax: campaign cards, D3FEND countermeasure descriptions, compliance framework/control descriptions, detection rule descriptions, threat-actor and technique reference descriptions, and the RT-import preview description - Fix the "Validated" status tooltip claiming a "≥2 tests" threshold when the real rule is ≥1 validated test with full detection; reworded the adjacent "Partial" tooltip for the same clarity - Generalize the technique review_required banner text away from "MITRE ATT&CK sync" — review can also be triggered by Atomic/Caldera/ Elastic/Sigma/LOLBAS imports, intel scans, and stale-detection checks --- frontend/src/components/StatusBadge.tsx | 4 ++-- frontend/src/components/compliance/ControlsTable.tsx | 8 +++++--- .../components/test-detail/DetectionRuleChecklist.tsx | 3 ++- frontend/src/components/test-detail/TeamTabs.tsx | 5 ++++- frontend/src/pages/CampaignsPage.tsx | 8 +++++--- frontend/src/pages/CompliancePage.tsx | 6 +++++- frontend/src/pages/ImportRTPage.tsx | 3 ++- frontend/src/pages/TechniqueDetailPage.tsx | 9 ++++++--- frontend/src/pages/ThreatActorDetailPage.tsx | 2 +- 9 files changed, 32 insertions(+), 16 deletions(-) diff --git a/frontend/src/components/StatusBadge.tsx b/frontend/src/components/StatusBadge.tsx index 215224e..c5259d9 100644 --- a/frontend/src/components/StatusBadge.tsx +++ b/frontend/src/components/StatusBadge.tsx @@ -29,14 +29,14 @@ const TOOLTIPS: Record What this control requires — and why it matters

-

- {control.description} -

+ )} diff --git a/frontend/src/components/test-detail/DetectionRuleChecklist.tsx b/frontend/src/components/test-detail/DetectionRuleChecklist.tsx index b402890..3c78766 100644 --- a/frontend/src/components/test-detail/DetectionRuleChecklist.tsx +++ b/frontend/src/components/test-detail/DetectionRuleChecklist.tsx @@ -16,6 +16,7 @@ import { type DetectionRuleItem, } from "../../api/detection-rules"; import type { User } from "../../types/models"; +import MarkdownText from "../MarkdownText"; const severityColors: Record = { critical: "bg-red-900/50 text-red-400 border-red-500/30", @@ -252,7 +253,7 @@ export default function DetectionRuleChecklist({ testId, user, canEdit }: Props) {isExpanded && (
{rule.description && ( -

{rule.description}

+ )} {/* Rule content */} diff --git a/frontend/src/components/test-detail/TeamTabs.tsx b/frontend/src/components/test-detail/TeamTabs.tsx index a62d950..9ed6679 100644 --- a/frontend/src/components/test-detail/TeamTabs.tsx +++ b/frontend/src/components/test-detail/TeamTabs.tsx @@ -629,7 +629,10 @@ export default function TeamTabs({ )}
{def.description && ( -

{def.description}

+ )} {def.d3fend_url && ( diff --git a/frontend/src/pages/CampaignsPage.tsx b/frontend/src/pages/CampaignsPage.tsx index 71719bd..05d5e25 100644 --- a/frontend/src/pages/CampaignsPage.tsx +++ b/frontend/src/pages/CampaignsPage.tsx @@ -14,6 +14,7 @@ import { import { listCampaigns, createCampaign, generateCampaignFromThreatActor, type CampaignSummary } from "../api/campaigns"; import { getThreatActors, type ThreatActorSummary } from "../api/threat-actors"; import { useAuth } from "../context/AuthContext"; +import MarkdownText from "../components/MarkdownText"; const statusColors: Record = { draft: "bg-gray-800/50 text-gray-400 border-gray-600/30", @@ -378,9 +379,10 @@ export default function CampaignsPage() { {campaign.name} {campaign.description && ( -

- {campaign.description} -

+ )} {/* Threat Actor */} diff --git a/frontend/src/pages/CompliancePage.tsx b/frontend/src/pages/CompliancePage.tsx index e875d81..22ee801 100644 --- a/frontend/src/pages/CompliancePage.tsx +++ b/frontend/src/pages/CompliancePage.tsx @@ -15,6 +15,7 @@ import { import { useAuth } from "../context/AuthContext"; import ComplianceGauge from "../components/compliance/ComplianceGauge"; import ControlsTable from "../components/compliance/ControlsTable"; +import MarkdownText from "../components/MarkdownText"; export default function CompliancePage() { const [selectedFrameworkId, setSelectedFrameworkId] = useState(null); @@ -238,7 +239,10 @@ export default function CompliancePage() { )} -

{activeFramework.description}

+ )} diff --git a/frontend/src/pages/ImportRTPage.tsx b/frontend/src/pages/ImportRTPage.tsx index 43799d9..aa93e3c 100644 --- a/frontend/src/pages/ImportRTPage.tsx +++ b/frontend/src/pages/ImportRTPage.tsx @@ -17,6 +17,7 @@ import { Braces, } from "lucide-react"; import { importRT, type RTImportPayload, type RTTechniqueEntry, type RTEvidenceEntry } from "../api/tests"; +import MarkdownText from "../components/MarkdownText"; /* ── Template JSON ─────────────────────────────────────────────────── */ @@ -324,7 +325,7 @@ export default function ImportRTPage() { {preview.techniques.length} techniques

{preview.description && ( -

{preview.description}

+ )}