[object Object]

← back to Rejected Prompts Viewer

Harden viewer: string-coerce esc(), fetch via location.origin (creds-in-URL safe)

0c45511f5ec2f114dd11c5b0bf95cffd0e92f467 · 2026-08-19 10:21:52 -0700 · Steve Abrams

Files touched

Diff

commit 0c45511f5ec2f114dd11c5b0bf95cffd0e92f467
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 19 10:21:52 2026 -0700

    Harden viewer: string-coerce esc(), fetch via location.origin (creds-in-URL safe)
---
 public/index.html | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/public/index.html b/public/index.html
index 709a5a0..4bfdf51 100644
--- a/public/index.html
+++ b/public/index.html
@@ -70,7 +70,7 @@ const el = id => document.getElementById(id);
 
 function fmt(ts){ if(!ts) return 'unknown time'; const d=new Date(ts);
   return isNaN(d)? ts : d.toLocaleString(undefined,{year:'numeric',month:'short',day:'numeric',hour:'numeric',minute:'2-digit'}); }
-function esc(s){ return (s||'').replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c])); }
+function esc(s){ return String(s==null?'':s).replace(/[&<>]/g,c=>({'&':'&amp;','<':'&lt;','>':'&gt;'}[c])); }
 
 function render(){
   const q = el('q').value.trim().toLowerCase();
@@ -123,7 +123,8 @@ el('q').oninput=render;
 el('density').oninput=()=>{ document.documentElement.style.setProperty('--cols',el('density').value); localStorage.setItem(LS('density'),el('density').value); };
 
 restore();
-fetch('/api/rejections').then(r=>r.json()).then(d=>{
+// resolve against location.origin (never carries userinfo) so a creds-in-URL open can't break the fetch
+fetch(location.origin + '/api/rejections').then(r=>r.json()).then(d=>{
   ALL = d.items||[];
   el('gen').textContent = d.generated ? `Generated ${fmt(d.generated)} · scanned ${d.scanned_files||'?'} transcripts` : '';
   buildCatChips(); render();

← ecf3b55 Rejected-prompts viewer: mine Claude policy declines from tr  ·  back to Rejected Prompts Viewer  ·  Widen to all 85 candidates + borderline toggle + table/list/ f3d573a →