diff --git a/frontend/src/RetailShield.jsx b/frontend/src/RetailShield.jsx index 3448ce4..ab1d3b8 100644 --- a/frontend/src/RetailShield.jsx +++ b/frontend/src/RetailShield.jsx @@ -508,6 +508,236 @@ function PlaybookModal({ threat, onClose }) { ) } +function getComplianceContext(mitre) { + if (mitre.startsWith('T1566')) return { + nature: 'A targeted spearphishing email was delivered to a privileged user account containing a malicious attachment. Potential credential compromise and account takeover are under investigation.', + affectedData: 'Senior executive email account, internal communications, and potentially captured credentials. The scope of any credential access is under active investigation.', + consequences: 'Risk of business email compromise, financial fraud, and further network penetration if credentials were captured. Immediate DPO notification assessment required.', + } + if (mitre.startsWith('T1110')) return { + nature: 'An automated credential stuffing attack targeted the POS admin portal using leaked credentials from a known breach dataset. Multiple accounts were confirmed compromised.', + affectedData: '4 compromised administrator accounts with potential access to POS transaction records, cardholder data, and administrative functions.', + consequences: 'Potential unauthorised access to cardholder data triggers PCI DSS notification obligation. UK GDPR Art.33 notification is required if personal data was accessed by an unauthorised party.', + } + if (mitre.startsWith('T1486')) return { + nature: 'Ransomware was deployed on an endpoint; files were encrypted and volume shadow copies deleted. Command-and-control communication to known threat actor infrastructure was confirmed.', + affectedData: '847 files encrypted on the affected endpoint. Potential spread to network shares. Any personal data within encrypted files requires urgent scoping to determine Art.33 obligation.', + consequences: 'Data unavailability, potential extortion demand, and systemic risk if ransomware has spread laterally. Art.33 notification is required if personal data is rendered permanently unavailable.', + } + if (mitre.startsWith('T1048')) return { + nature: 'Customer database records were exfiltrated via DNS tunnelling to external threat actor infrastructure. Approximately 2.1 GB of data was staged and transmitted before DNS blocking was applied.', + affectedData: 'Customer PII database (estimated 2.1 GB): likely includes names, contact details, purchase history, and potentially payment card references held by the data processor.', + consequences: 'High-risk personal data breach with near-certain likelihood of harm to data subjects. ICO Art.33 notification is mandatory. Individual notification under Art.34 is likely required.', + } + return { + nature: 'A security incident has been detected and is under active investigation by the security team.', + affectedData: '[REVIEWER: Assess and document which data categories and approximate volumes were affected]', + consequences: '[REVIEWER: Assess the likely consequences of the breach for affected individuals and the organisation]', + } +} + +function ComplianceReportCard({ report, clock }) { + const [expanded, setExpanded] = React.useState(false) + const ncscMs = report.ncscDeadline - clock + const icoMs = report.icoDeadline - clock + + const fmtMs = ms => { + if (ms <= 0) return 'OVERDUE' + const h = Math.floor(ms / 3600000) + const m = Math.floor((ms % 3600000) / 60000) + const sc = Math.floor((ms % 60000) / 1000) + return `${h}h ${String(m).padStart(2,'0')}m ${String(sc).padStart(2,'0')}s` + } + + const ncscStr = fmtMs(ncscMs) + const icoStr = fmtMs(icoMs) + const ncscOver = ncscMs <= 0 + const icoOver = icoMs <= 0 + const ncscUrgent = !ncscOver && ncscMs < 6 * 3600000 + const icoUrgent = !icoOver && icoMs < 24 * 3600000 + + const ctx = getComplianceContext(report.mitre) + + const draftText = [ + 'UK REGULATORY COMPLIANCE DRAFT REPORT', + 'RetailShield — Incident Compliance Notification', + '=================================================', + '', + `Generated : ${new Date().toLocaleString('en-GB')}`, + 'Classification : DRAFT — REQUIRES HUMAN REVIEW BEFORE SUBMISSION', + 'Organisation : [REVIEWER: Insert organisation name]', + '', + '1. INCIDENT OVERVIEW', + '--------------------', + `Incident Title : ${report.incidentTitle}`, + `Incident ID : ${report.id}`, + `Detection Time : ${report.detectionTime.toLocaleString('en-GB')}`, + 'Severity : CRITICAL', + `MITRE Technique : ${report.mitre} — ${report.tactic}`, + `Affected System : ${report.affectedSystems}`, + 'Current Status : Contained by RetailShield automated playbooks', + '', + '2. NATURE OF THE BREACH', + '-----------------------', + ctx.nature, + '', + '3. CATEGORIES AND APPROXIMATE VOLUME OF AFFECTED DATA', + '------------------------------------------------------', + ctx.affectedData, + '', + '4. LIKELY CONSEQUENCES OF THE BREACH', + '-------------------------------------', + ctx.consequences, + '', + '5. MEASURES TAKEN OR PROPOSED', + '------------------------------', + 'RetailShield Automated Response:', + ...report.autoActions.map(a => ` • ${a}`), + '', + '[REVIEWER: Add any additional manual measures taken by your team]', + '', + '6. NOTIFICATION TIMELINE', + '------------------------', + `Detection Time : ${report.detectionTime.toLocaleString('en-GB')}`, + `NCSC Early-Warning (24h) : ${report.ncscDeadline.toLocaleString('en-GB')}`, + `ICO Full Report (72h) : ${report.icoDeadline.toLocaleString('en-GB')}`, + '', + '[REVIEWER: Record actual submission timestamps here]', + '', + '7. DATA CONTROLLER CONTACT DETAILS', + '------------------------------------', + 'Organisation : [REVIEWER: Complete before submission]', + 'Data Controller : [REVIEWER: Full name and title]', + 'Contact Email : [REVIEWER: security@yourorganisation.com]', + 'DPO : [REVIEWER: Provide DPO contact details if applicable]', + 'Reference No. : [REVIEWER: Assign your internal incident reference]', + '', + '=================================================', + 'IMPORTANT DISCLAIMER', + 'This draft was generated automatically by RetailShield v1.0 (ShieldTech Ltd).', + 'A qualified Data Protection Officer or legal counsel MUST review and approve', + 'this report before submission. Do NOT submit directly to regulators without', + 'prior human review and authorisation.', + '', + 'Submission Portals:', + ' • ICO: https://ico.org.uk/for-organisations/report-a-breach/', + ' • NCSC: https://www.ncsc.gov.uk/section/about-this-website/incident-management', + '=================================================', + ].join('\n') + + const handleDownload = () => { + const blob = new Blob([draftText], { type: 'text/plain' }) + const url = URL.createObjectURL(blob) + const a = document.createElement('a') + a.href = url + a.download = `RetailShield-Compliance-${report.id}.txt` + document.body.appendChild(a) + a.click() + document.body.removeChild(a) + URL.revokeObjectURL(url) + } + + const ncscColor = ncscOver ? C.dim : ncscUrgent ? C.red : C.text + const icoColor = icoOver ? C.dim : icoUrgent ? C.orange : C.text + + return ( +
+
setExpanded(e => !e)}> + CRITICAL + {report.incidentTitle} + {report.mitre} + 📍 {report.affectedSystems} + {expanded ? '▲' : '▼'} +
+ +
+
+
+
NCSC 24h Early-Warning (CSR Bill)
+
{ncscStr}
+
Deadline: {report.ncscDeadline.toLocaleString('en-GB')}
+
+
+
+
ICO 72h Full Report (UK GDPR Art.33)
+
{icoStr}
+
Deadline: {report.icoDeadline.toLocaleString('en-GB')}
+
+
+
+ + ⚖️ Submit to ICO ↗ + + + 🏗 Submit to NCSC ↗ + + +
+
+ + {expanded && ( +
+
+
Incident Summary
+
+ {[ + ['Incident Title', report.incidentTitle], + ['Detection Time', report.detectionTime.toLocaleString('en-GB')], + ['MITRE Technique', `${report.mitre} — ${report.tactic}`], + ['Affected System', report.affectedSystems], + ['Severity', 'CRITICAL'], + ].map(([k, v]) => ( + + {k} + {v} + + ))} +
+
+ +
UK Draft Compliance Report — 7 Sections
+ {[ + { num:'1', title:'Incident Overview', + body:`Detected: ${report.detectionTime.toLocaleString('en-GB')} · Technique: ${report.mitre} (${report.tactic}) · System: ${report.affectedSystems}. Status: Contained by RetailShield automated response playbooks.` }, + { num:'2', title:'Nature of the Breach', body: ctx.nature }, + { num:'3', title:'Affected Data Categories & Volume', body: ctx.affectedData }, + { num:'4', title:'Likely Consequences', body: ctx.consequences }, + { num:'5', title:'Measures Taken', + body: report.autoActions.map(a => `• ${a}`).join('\n') + '\n\n[REVIEWER: Add any manual measures taken by your team]' }, + { num:'6', title:'Notification Timeline', + body:`Detection : ${report.detectionTime.toLocaleString('en-GB')}\nNCSC Deadline : ${report.ncscDeadline.toLocaleString('en-GB')} (24h — CSR Bill)\nICO Deadline : ${report.icoDeadline.toLocaleString('en-GB')} (72h — UK GDPR Art.33)\n\n[REVIEWER: Record actual submission timestamps here]` }, + { num:'7', title:'Data Controller Contact', + body:'[REVIEWER: Organisation name]\n[REVIEWER: Data Controller — full name & title]\n[REVIEWER: Contact email address]\n[REVIEWER: DPO details if applicable]\n[REVIEWER: Internal incident reference number]' }, + ].map(({ num, title, body }) => { + const needsReview = body.includes('[REVIEWER') + return ( +
+
+ §{num} + {title} + {needsReview && ACTION REQUIRED} +
+
{body}
+
+ ) + })} + +
+
+ ⚠ IMPORTANT DISCLAIMER: This draft was generated automatically by RetailShield v1.0. A qualified Data Protection Officer or legal counsel MUST review and approve this report before submission to regulators. Do NOT submit directly to the ICO or NCSC without prior human authorisation. +
+
+
+ )} +
+ ) +} + export default function RetailShield() { const [threats, setThreats] = useState(BASE_THREATS) const [filter, setFilter] = useState('all') @@ -522,6 +752,7 @@ export default function RetailShield() { const [vulnProg, setVulnProg] = useState(0) const [briefing, setBriefing] = useState(null) const [briefStatus, setBriefStatus] = useState(null) + const [complianceReports, setComplianceReports] = useState([]) useEffect(() => { const id = setInterval(() => setClock(new Date()), 1000); return () => clearInterval(id) }, []) @@ -544,12 +775,29 @@ export default function RetailShield() { if (simStatus === 'running') return setSimStatus('running') setScore(s => Math.max(10, s - 20)) + setComplianceReports([]) ATTACK_SIM_EVENTS.forEach((event, i) => { setTimeout(() => { const threat = { ...event, id: Date.now() + i, ts: Date.now() } setThreats(prev => [threat, ...prev.slice(0, 14)]) setBanner(threat) setTimeout(() => setBanner(null), 3500) + if (event.severity === 'critical') { + const detTime = new Date() + const report = { + id: `RS-${Date.now()}-${i}`, + incidentTitle: event.name, + severity: event.severity, + detectionTime: detTime, + mitre: event.mitre, + tactic: event.tactic, + affectedSystems: event.device, + autoActions: event.playbook.auto, + ncscDeadline: new Date(detTime.getTime() + 24 * 3600000), + icoDeadline: new Date(detTime.getTime() + 72 * 3600000), + } + setComplianceReports(prev => [...prev, report]) + } if (i === ATTACK_SIM_EVENTS.length - 1) { setTimeout(() => { setSimStatus('complete'); setTimeout(() => setSimStatus(null), 6000) }, 800) } @@ -882,6 +1130,32 @@ export default function RetailShield() { )}
+
+ {complianceReports.length === 0 ? ( +
+ +
+
+ UK Compliance Reports + No reportable incidents +
+
When a CRITICAL incident is detected, UK GDPR (ICO 72h) and CSR Bill (NCSC 24h) compliance reports will appear here with live countdown timers and pre-filled draft notifications.
+
+
+ ) : ( +
+
+ 🚨 + UK Regulatory Notification Required + + {complianceReports.length} critical incident{complianceReports.length > 1 ? 's' : ''} — countdown active + +
+ {complianceReports.map(r => )} +
+ )} +
+
🆘 Emergency Contacts