diff --git a/DECISIONS.md b/DECISIONS.md index 5bda840..7281cd4 100644 --- a/DECISIONS.md +++ b/DECISIONS.md @@ -32,6 +32,18 @@ This file documents major architectural decisions and their rationale. --- +## Decision: XSS Prevention in Mission Control Dashboard + +**Date:** 2026-03-02 + +**Context:** The Mission Control dashboard was using `innerHTML` to render dependency details and recommendations from the `/health/sovereignty` endpoint. While these sources are currently internal, using `innerHTML` with dynamic data is a security risk and violates the "Non-Negotiable Rules" in `AGENTS.md`. + +**Decision:** Refactored the JavaScript in `mission_control.html` to use `document.createElement` and `textContent` for all dynamic data rendering. + +**Rationale:** This approach provides built-in XSS protection by ensuring that any data from the API is treated as plain text rather than HTML, fulfilling the security requirements of the project. + +--- + ## Add New Decisions Above This Line When making significant architectural choices, document: diff --git a/src/dashboard/templates/mission_control.html b/src/dashboard/templates/mission_control.html index c1bad5e..8e5b64e 100644 --- a/src/dashboard/templates/mission_control.html +++ b/src/dashboard/templates/mission_control.html @@ -203,27 +203,51 @@ async function loadSovereignty() { const scoreColor = dep.sovereignty_score >= 9 ? 'var(--success)' : dep.sovereignty_score >= 7 ? 'var(--warning)' : 'var(--danger)'; - card.innerHTML = ` -
No recommendations — system optimal
'; + const p = document.createElement('p'); + p.style.color = 'var(--text-muted)'; + p.textContent = 'No recommendations — system optimal'; + recs.appendChild(p); } } catch (error) {