diff --git a/.gitignore b/.gitignore
index c513b1e..a2c88a8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -52,3 +52,6 @@ benchmarks/*/results/
# Local-only benchmark data: third-party datasets we re-fetch via bootstrap scripts
benchmarks/faithfulness/*.jsonl
# HHEM model cache lives under HF_HOME by default; not in this repo.
+
+# Playwright MCP browser-verification artifacts
+.playwright-mcp/
diff --git a/site/trace.js b/site/trace.js
index 9f85548..788a65d 100644
--- a/site/trace.js
+++ b/site/trace.js
@@ -31,7 +31,10 @@ function resolveVerdicts() {
pill.classList.remove('pending');
pill.classList.add(v.cls);
const scoreTxt = score ? ` · ${score}` : '';
- pill.innerHTML = `${v.label}${scoreTxt}`;
+ const vt = document.createElement('span');
+ vt.className = 'vt';
+ vt.textContent = `${v.label}${scoreTxt}`;
+ pill.replaceChildren(vt);
});
}
@@ -72,11 +75,15 @@ function buildLedger(claims) {
li.href = `#${c.id}`;
li.className = `led ${c.kind}`;
const v = VERDICTS[c.kind];
- li.innerHTML = `
- ${v.glyph}
- ${c.n}
- ${c.title}
- `;
+ // c.title came from .textContent (entities already decoded) — injecting
+ // it through innerHTML would re-open the XSS the server-side escaping
+ // closed. Build the row with createElement/textContent only.
+ for (const [cls, text] of [["glyph", v.glyph], ["cid", c.n], ["lbl", c.title]]) {
+ const span = document.createElement('span');
+ span.className = cls;
+ span.textContent = text;
+ li.appendChild(span);
+ }
list.appendChild(li);
});
const total = document.getElementById('led-total');