[object Object]

← back to Nationalrealestate

CCK#2 verified fixes: HTML-escape admin provenance fields, guard localStorage (Safari private)

d8824b444fe2b61421610f962aabe38598c38996 · 2026-07-21 13:34:34 -0700 · Steve Abrams

Files touched

Diff

commit d8824b444fe2b61421610f962aabe38598c38996
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue Jul 21 13:34:34 2026 -0700

    CCK#2 verified fixes: HTML-escape admin provenance fields, guard localStorage (Safari private)
---
 public/admin.html   | 5 +++--
 public/brokers.html | 6 ++++--
 2 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/public/admin.html b/public/admin.html
index 01b5d7c..c9d8845 100644
--- a/public/admin.html
+++ b/public/admin.html
@@ -58,6 +58,7 @@ const JOBS = ['zillow','redfin','fhfa','acs','derive','score','alerts','brokers'
 // standing rule: every admin card shows the record's created date AND time, visible on-card
 const fmtWhen = iso => new Date(iso).toLocaleString(undefined,
   { year:'numeric', month:'short', day:'numeric', hour:'numeric', minute:'2-digit' });
+const esc = s => String(s).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]));
 
 function renderBtns(busy){
   const el = document.getElementById('runbtns');
@@ -89,8 +90,8 @@ async function loadRuns(){
       <div class="rows"><span>upserted <b>${(+r.rows_upserted||0).toLocaleString()}</b></span>
         <span>skipped <b>${(+r.rows_skipped||0).toLocaleString()}</b></span>
         <span>run <b>#${r.id}</b></span></div>
-      ${r.notes ? `<div class="notes">${r.notes}</div>` : ''}
-      ${r.file_hash ? `<div class="hash">sha256 ${r.file_hash.slice(0,20)}…</div>` : ''}
+      ${r.notes ? `<div class="notes">${esc(r.notes)}</div>` : ''}
+      ${r.file_hash ? `<div class="hash">sha256 ${esc(r.file_hash.slice(0,20))}…</div>` : ''}
     </div>`).join('');
 }
 
diff --git a/public/brokers.html b/public/brokers.html
index f8aedde..87ab91d 100644
--- a/public/brokers.html
+++ b/public/brokers.html
@@ -68,7 +68,9 @@
 <script src="/col-resize.js"></script>
 <script>
 const PAGE = 500;
-const S = { state: localStorage.getItem('usreBrk.state') || '', q: '', firm: '', offset: 0, total: 0 };
+const LS = { get(k){ try { return localStorage.getItem(k); } catch { return null; } },
+             set(k,v){ try { localStorage.setItem(k,v); } catch {} } };
+const S = { state: LS.get('usreBrk.state') || '', q: '', firm: '', offset: 0, total: 0 };
 
 const FIELDS = [
   { k: 'license_no',     l: 'License #', def: 1, col: 1 },
@@ -94,7 +96,7 @@ async function loadStats() {
   box.addEventListener('click', e => {
     const c = e.target.closest('.st-chip'); if (!c) return;
     S.state = c.dataset.st; S.offset = 0;
-    localStorage.setItem('usreBrk.state', S.state);
+    LS.set('usreBrk.state', S.state);
     box.querySelectorAll('.st-chip').forEach(x => x.classList.toggle('active', x.dataset.st === S.state));
     loadPage();
   }, { once: false });

← 731695f Contrarian fixes: thin-market floor (pop<50k or <10 monthly  ·  back to Nationalrealestate  ·  auto-save: 2026-07-21T14:07:54 (8 files) — package-lock.json 31f2bbc →