From a0022fbeaf3a7b24339e209be156a300db53ca24 Mon Sep 17 00:00:00 2001 From: david kiania Date: Thu, 2 Jul 2026 09:47:40 +0300 Subject: [PATCH] fix(security): escape API strings, pin CDN scripts, add CSP (FO-SEC-01/02/03) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tickets code escaped HTML, but the logistics + fuel renderers and the error banners interpolated API strings straight into innerHTML. Fuel Log fields (driver, department, fuel_type, plate) come from WhatsApp messages and vehicle/driver names from the Tracksolid registry — both user-controlled — so this was a stored-XSS path into every dispatcher's browser. - Hoist escapeHtml into HELPERS + add esc(); route every logistics/fuel renderer and the three error banners through it (21 -> 37 escaped call sites). - SRI integrity + crossorigin on Chart.js 4.4.1 and maplibre-gl 4.7.1 JS/CSS. - Caddyfile: CSP (self + pinned CDNs + CARTO basemap + the two fleet APIs), X-Content-Type-Options, Referrer-Policy, frame-ancestors 'none', -Server. Validated with `caddy validate` inside the deployed image. - loadLive(): check r.ok; pause the 15s live poll while hidden or off the Tickets tab, refresh immediately on return (FO-BUG-01/02). - Missing-API_BASE fallback flipped staging -> prod, matching the documented design (FO-OPS-01). Inline app script passes `node --check`. Audit + plan + work log in docs/260702_*. Local only; not deployed. Co-Authored-By: Claude Fable 5 --- Caddyfile | 13 +++++++ docs/260702_audit_report.md | 67 +++++++++++++++++++++++++++++++++++ docs/260702_fix_plan.md | 27 ++++++++++++++ docs/260702_work_done.md | 32 +++++++++++++++++ src/index.html | 70 +++++++++++++++++++++++++------------ 5 files changed, 186 insertions(+), 23 deletions(-) create mode 100644 docs/260702_audit_report.md create mode 100644 docs/260702_fix_plan.md create mode 100644 docs/260702_work_done.md diff --git a/Caddyfile b/Caddyfile index fd7261c..20b6ae9 100644 --- a/Caddyfile +++ b/Caddyfile @@ -8,6 +8,19 @@ root * /srv encode zstd gzip + # Security headers (FO-SEC-03). CSP allows self + the two pinned CDNs, the + # CARTO basemap (styles/tiles/fonts) and the fleet APIs; SRI in index.html + # pins the CDN payloads themselves. frame-ancestors 'none' = no clickjacking. + # script-src keeps 'unsafe-inline' because the whole app is one inline + # - + + - - + +