diff --git a/web/public/app.js b/web/public/app.js index 252a8bf..38a7cab 100644 --- a/web/public/app.js +++ b/web/public/app.js @@ -595,11 +595,9 @@ $('#findingModal').addEventListener('click', (e) => { if (e.target.id === 'findi const KILL_CHAIN_STAGES = ['recon', 'initial-access', 'execution', 'privesc', 'lateral', 'exfil', 'impact']; -// Bright, saturated palette for the dark graph canvas — the severity chip -// colors elsewhere are tuned for text-on-light-background legibility and -// read as muddy on a dark node graph. -const CANVAS_SEV_COLOR = { critical: '#ff6b5b', high: '#ffab52', medium: '#f0cf5c', low: '#7fd99a', info: '#8fa3ef' }; -function canvasColor(sev) { return CANVAS_SEV_COLOR[['critical', 'high', 'medium', 'low', 'info'][sevRank(sev)]]; } +// Same severity tokens the rest of the console uses — the graph canvas +// follows the light/dark theme instead of a fixed dark palette. +function canvasColor(sev) { return `var(--sev-${['critical', 'high', 'medium', 'low', 'info'][sevRank(sev)]}-fg)`; } function nodeIcon(f) { const t = `${f.title} ${f.evidence} ${f.cwe} ${f.stage}`.toLowerCase(); @@ -671,20 +669,20 @@ function renderAttackPath(container, findings, target) { const nodeSvg = (n) => { if (n.root) { return ` - - 🎯 - ${esc(trimMid(n.label, 26))} + + 🎯 + ${esc(trimMid(n.label, 26))} `; } const f = n.finding; const color = canvasColor(f.severity); const x = n.x - NODE_W / 2, y = n.y - NODE_H / 2; return ` - + ${nodeIcon(f)} - ${esc(trimMid(f.title, 22))} - ${esc((f.mitre || f.owasp || f.cwe || n.stageLabel || '').slice(0, 26))} - + ${esc(trimMid(f.title, 22))} + ${esc((f.mitre || f.owasp || f.cwe || n.stageLabel || '').slice(0, 26))} + `; }; @@ -692,8 +690,8 @@ function renderAttackPath(container, findings, target) { ${!hasStages ? '
No kill-chain stage data yet — shown as a flat graph from the target.
' : ''}
- ${groups.map((g, ci) => ``).join('')} - ${edges.map(([a, b]) => ``).join('')} + ${groups.map((g, ci) => ``).join('')} + ${edges.map(([a, b]) => ``).join('')} ${nodes.map(nodeSvg).join('')}
diff --git a/web/public/style.css b/web/public/style.css index 1122838..639e088 100644 --- a/web/public/style.css +++ b/web/public/style.css @@ -311,14 +311,10 @@ textarea { resize: vertical; min-height: 72px; } /* Generative Attack Path Chaining */ .attackpath-empty { font-size: 12.5px; color: var(--text-faint); padding: var(--sp-5); text-align: center; border: 1px dashed var(--border-strong); border-radius: var(--radius-sm); } -/* The graph canvas is intentionally fixed-dark regardless of the app theme — - a node/edge map reads better with bright severity colors against a near- - black surface, the way NodeZero/attack-graph tools render it, and it stays - legible whether the rest of the console is in light or dark mode. */ -.ap-canvas-wrap { border-radius: var(--radius-md); overflow: auto; background: #0f1115; border: 1px solid #24262d; } +.ap-canvas-wrap { border-radius: var(--radius-md); overflow: auto; background: var(--surface-2); border: 1px solid var(--border); } .ap-canvas { display: block; min-width: 100%; } .ap-canvas text { font-family: var(--sans); } -.ap-node-g:hover rect:first-child { filter: brightness(1.35); } +.ap-node-g:hover rect:first-child { filter: brightness(0.97); } /* findings table */ .data-table { width: 100%; border-collapse: collapse; font-size: 12.5px; }